Fancy skybox :D
4
Makefile
@ -43,13 +43,13 @@ else
|
||||
CFLAGS += -O3
|
||||
endif
|
||||
|
||||
CXXFLAGS += -std=gnu++11 -Wall -pedantic $(fpic) -DHAVE_ZIP_DEFLATE
|
||||
CXXFLAGS += -std=gnu++11 -Wall -pedantic $(fpic) -DHAVE_ZIP_DEFLATE $(shell pkg-config assimp --cflags)
|
||||
CFLAGS += -std=gnu99 -Wall -pedantic $(fpic) -DHAVE_ZIP_DEFLATE
|
||||
|
||||
SOURCES := $(wildcard *.cpp) $(wildcard */*.cpp)
|
||||
CSOURCES := $(wildcard *.c) $(wildcard */*.c)
|
||||
OBJECTS := $(SOURCES:.cpp=.o) $(CSOURCES:.c=.o)
|
||||
LIBS += $(GL_LIB)
|
||||
LIBS += $(GL_LIB) $(shell pkg-config assimp --libs)
|
||||
|
||||
all: $(TARGET)
|
||||
|
||||
|
@ -3,83 +3,61 @@
|
||||
#include <gl/shader.hpp>
|
||||
#include <gl/vertex_array.hpp>
|
||||
#include <gl/texture.hpp>
|
||||
#include <gl/mesh.hpp>
|
||||
#include <memory>
|
||||
#include <cstdint>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace glm;
|
||||
using namespace GL;
|
||||
|
||||
class HeightGrid
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
void init(unsigned size)
|
||||
void init(const std::string& path)
|
||||
{
|
||||
init_vertices(size);
|
||||
init_indices(size);
|
||||
vector<VertexArray::Array> arrays = {
|
||||
{ Shader::VertexLocation, 2, GL_SHORT, GL_FALSE, 0, 0 },
|
||||
};
|
||||
array.setup(arrays, &vertex, &elems);
|
||||
auto meshes = load_scene(path);
|
||||
|
||||
for (auto& mesh : meshes)
|
||||
{
|
||||
auto drawable = Util::make_unique<Drawable>();
|
||||
drawable->vertex.init(GL_ARRAY_BUFFER, mesh.vbo, Buffer::None);
|
||||
drawable->elems.init(GL_ELEMENT_ARRAY_BUFFER, mesh.ibo, Buffer::None);
|
||||
drawable->array.setup(mesh.arrays, &drawable->vertex,
|
||||
&drawable->elems);
|
||||
drawable->indices = mesh.ibo.size();
|
||||
drawables.push_back(move(drawable));
|
||||
|
||||
}
|
||||
|
||||
mat4 model = translate(mat4(1.0), vec3(0, -5, -10));
|
||||
uniform_offset.init(GL_UNIFORM_BUFFER, sizeof(model),
|
||||
Buffer::None, value_ptr(model), Shader::VertexSlot1);
|
||||
}
|
||||
|
||||
void render()
|
||||
{
|
||||
array.bind();
|
||||
glDrawElements(GL_TRIANGLE_STRIP, elements, GL_UNSIGNED_SHORT, nullptr);
|
||||
array.unbind();
|
||||
uniform_offset.bind();
|
||||
for (auto& drawable : drawables)
|
||||
{
|
||||
drawable->array.bind();
|
||||
glDrawElements(GL_TRIANGLES, drawable->indices,
|
||||
GL_UNSIGNED_INT, nullptr);
|
||||
drawable->array.unbind();
|
||||
}
|
||||
uniform_offset.unbind();
|
||||
}
|
||||
|
||||
private:
|
||||
VertexArray array;
|
||||
Buffer vertex;
|
||||
Buffer elems;
|
||||
unsigned elements = 0;
|
||||
|
||||
void init_vertices(unsigned size)
|
||||
struct Drawable
|
||||
{
|
||||
vector<GLshort> vertices;
|
||||
vertices.reserve(2 * size * size);
|
||||
for (unsigned y = 0; y < size; y++)
|
||||
{
|
||||
for (unsigned x = 0; x < size; x++)
|
||||
{
|
||||
vertices.push_back(x);
|
||||
vertices.push_back(int(size) - 1 - y);
|
||||
}
|
||||
}
|
||||
|
||||
vertex.init(GL_ARRAY_BUFFER, 2 * size * size * sizeof(GLshort), Buffer::None, vertices.data());
|
||||
}
|
||||
|
||||
void init_indices(unsigned size)
|
||||
{
|
||||
elements = (size - 1) * (2 * size + 1);
|
||||
|
||||
vector<GLushort> indices;
|
||||
indices.reserve(elements);
|
||||
|
||||
int pos = 0;
|
||||
for (unsigned y = 0; y < size - 1; y++)
|
||||
{
|
||||
int dir_odd = -int(size) + ((y & 1) ? -1 : 1);
|
||||
int dir_even = size;
|
||||
|
||||
for (unsigned x = 0; x < 2 * size - 1; x++)
|
||||
{
|
||||
indices.push_back(pos);
|
||||
pos += (x & 1) ? dir_odd : dir_even;
|
||||
}
|
||||
indices.push_back(pos);
|
||||
indices.push_back(pos);
|
||||
}
|
||||
|
||||
elems.init(GL_ELEMENT_ARRAY_BUFFER, elements * sizeof(GLushort), Buffer::None, indices.data());
|
||||
}
|
||||
VertexArray array;
|
||||
Buffer vertex;
|
||||
Buffer elems;
|
||||
size_t indices;
|
||||
};
|
||||
Buffer uniform_offset;
|
||||
vector<unique_ptr<Drawable>> drawables;
|
||||
};
|
||||
|
||||
class HeightmapApp : public LibretroGLApplication
|
||||
@ -139,12 +117,24 @@ class HeightmapApp : public LibretroGLApplication
|
||||
|
||||
global.camera_pos = vec4(player_pos.x, player_pos.y, player_pos.z, 0.0);
|
||||
|
||||
global_fragment.camera_pos = global.camera_pos;
|
||||
global_fragment.light_pos = vec4(100.0, 100.0, 100.0, 1.0);
|
||||
global_fragment.light_color = vec4(1.0);
|
||||
global_fragment.light_ambient = vec4(0.25);
|
||||
|
||||
GlobalTransforms *buf;
|
||||
if (global_buffer.map(buf))
|
||||
{
|
||||
*buf = global;
|
||||
global_buffer.unmap();
|
||||
}
|
||||
|
||||
GlobalFragmentData *frag_buf;
|
||||
if (global_fragment_buffer.map(frag_buf))
|
||||
{
|
||||
*frag_buf = global_fragment;
|
||||
global_fragment_buffer.unmap();
|
||||
}
|
||||
}
|
||||
|
||||
void viewport_changed(const Resolution& res) override
|
||||
@ -169,7 +159,7 @@ class HeightmapApp : public LibretroGLApplication
|
||||
vec3 right_walk_dir = vec3(rotate_y_right * vec4(0, 0, -1, 1));
|
||||
|
||||
|
||||
vec3 mod_speed = buttons.r ? vec3(120.0f) : vec3(60.0f);
|
||||
vec3 mod_speed = buttons.r ? vec3(240.0f) : vec3(120.0f);
|
||||
vec3 velocity = player_look_dir * vec3(analog.y * -0.25f) +
|
||||
right_walk_dir * vec3(analog.x * 0.25f);
|
||||
|
||||
@ -177,30 +167,6 @@ class HeightmapApp : public LibretroGLApplication
|
||||
update_global_data();
|
||||
}
|
||||
|
||||
void bind_all()
|
||||
{
|
||||
global_buffer.bind();
|
||||
global_frag_buffer.bind();
|
||||
shader.use();
|
||||
tex.bind(0);
|
||||
sampler.bind(0);
|
||||
|
||||
skybox.tex.bind(1);
|
||||
skybox.sampler.bind(1);
|
||||
}
|
||||
|
||||
void unbind_all()
|
||||
{
|
||||
global_buffer.unbind();
|
||||
global_frag_buffer.unbind();
|
||||
shader.unbind();
|
||||
tex.unbind(0);
|
||||
sampler.unbind(0);
|
||||
|
||||
skybox.tex.unbind(1);
|
||||
skybox.sampler.unbind(1);
|
||||
}
|
||||
|
||||
void run(float delta, const InputState& input, GLuint) override
|
||||
{
|
||||
auto analog = input.analog;
|
||||
@ -214,12 +180,6 @@ class HeightmapApp : public LibretroGLApplication
|
||||
analog.ry = 0.0f;
|
||||
update_input(delta, analog, input.pressed);
|
||||
|
||||
if (input.triggered.a)
|
||||
{
|
||||
foo_define ^= 1;
|
||||
shader.set_global_define("FOO", foo_define);
|
||||
}
|
||||
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(0.3f, 0.3f, 0.3f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
@ -228,13 +188,26 @@ class HeightmapApp : public LibretroGLApplication
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
|
||||
bind_all();
|
||||
grid.render();
|
||||
global_buffer.bind();
|
||||
global_fragment_buffer.bind();
|
||||
|
||||
skybox.tex.bind(0);
|
||||
skybox.sampler.bind(0);
|
||||
|
||||
shader.use();
|
||||
scene.render();
|
||||
shader.unbind();
|
||||
|
||||
skybox.shader.use();
|
||||
skybox.arrays.bind();
|
||||
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
|
||||
skybox.arrays.unbind();
|
||||
unbind_all();
|
||||
skybox.shader.unbind();
|
||||
|
||||
global_buffer.unbind();
|
||||
global_fragment_buffer.unbind();
|
||||
skybox.tex.unbind(0);
|
||||
skybox.sampler.unbind(0);
|
||||
}
|
||||
|
||||
void get_context_version(unsigned& major, unsigned& minor) const override
|
||||
@ -245,10 +218,9 @@ class HeightmapApp : public LibretroGLApplication
|
||||
|
||||
void load() override
|
||||
{
|
||||
global_buffer.init(GL_UNIFORM_BUFFER, sizeof(global), Buffer::WriteOnly);
|
||||
|
||||
vec4 global_color(0.8f, 0.6f, 0.2f, 1.0f);
|
||||
global_frag_buffer.init(GL_UNIFORM_BUFFER, sizeof(global_color), Buffer::None, value_ptr(global_color), 1);
|
||||
global_buffer.init(GL_UNIFORM_BUFFER, sizeof(global), Buffer::WriteOnly, nullptr, Shader::GlobalVertexData);
|
||||
global_fragment_buffer.init(GL_UNIFORM_BUFFER,
|
||||
sizeof(global_fragment), Buffer::WriteOnly, nullptr, Shader::GlobalFragmentData);
|
||||
|
||||
player_pos = vec3(0.0f);
|
||||
player_look_dir = vec3(0, 0, -1);
|
||||
@ -256,19 +228,14 @@ class HeightmapApp : public LibretroGLApplication
|
||||
player_view_deg_y = 0.0f;
|
||||
|
||||
shader.init(path("test.vs"), path("test.fs"));
|
||||
Shader::reserve_global_define("FOO", 1);
|
||||
grid.init(128);
|
||||
|
||||
tex.load_texture_2d({Texture::Texture2D, { path("app/test.png") }, true });
|
||||
sampler.init(Sampler::TrilinearClamp);
|
||||
|
||||
scene.init(path("test.obj"));
|
||||
skybox.tex.load_texture_2d({Texture::TextureCube, {
|
||||
path("app/skybox_autum_forest_right.png"),
|
||||
path("app/skybox_pine_forest_left.png"),
|
||||
path("app/skybox_autum_forest_top.png"),
|
||||
path("app/skybox_autum_forest_bottom.png"),
|
||||
path("app/skybox_pine_forest_front.png"),
|
||||
path("app/skybox_autum_forest_back.png"),
|
||||
path("app/xpos.png"),
|
||||
path("app/xneg.png"),
|
||||
path("app/ypos.png"),
|
||||
path("app/yneg.png"),
|
||||
path("app/zpos.png"),
|
||||
path("app/zneg.png"),
|
||||
}, true});
|
||||
skybox.sampler.init(Sampler::TrilinearClamp);
|
||||
skybox.shader.init(path("skybox.vs"), path("skybox.fs"));
|
||||
@ -299,16 +266,21 @@ class HeightmapApp : public LibretroGLApplication
|
||||
vec4 camera_pos;
|
||||
};
|
||||
|
||||
struct GlobalFragmentData
|
||||
{
|
||||
vec4 camera_pos;
|
||||
vec4 light_pos;
|
||||
vec4 light_color;
|
||||
vec4 light_ambient;
|
||||
};
|
||||
|
||||
GlobalTransforms global;
|
||||
GlobalFragmentData global_fragment;
|
||||
Buffer global_buffer;
|
||||
Buffer global_frag_buffer;
|
||||
Buffer global_fragment_buffer;
|
||||
|
||||
Shader shader;
|
||||
unsigned foo_define = 0;
|
||||
|
||||
HeightGrid grid;
|
||||
|
||||
Texture tex;
|
||||
Sampler sampler;
|
||||
Scene scene;
|
||||
|
||||
struct
|
||||
{
|
||||
@ -322,6 +294,6 @@ class HeightmapApp : public LibretroGLApplication
|
||||
|
||||
unique_ptr<LibretroGLApplication> libretro_gl_application_create()
|
||||
{
|
||||
return unique_ptr<LibretroGLApplication>(new HeightmapApp);
|
||||
return Util::make_unique<HeightmapApp>();
|
||||
}
|
||||
|
||||
|
Before Width: | Height: | Size: 2.2 MiB |
Before Width: | Height: | Size: 2.4 MiB |
Before Width: | Height: | Size: 1.8 MiB |
Before Width: | Height: | Size: 1.1 MiB |
Before Width: | Height: | Size: 1.9 MiB |
Before Width: | Height: | Size: 2.0 MiB |
BIN
app/xneg.png
Normal file
After Width: | Height: | Size: 225 KiB |
BIN
app/xpos.png
Normal file
After Width: | Height: | Size: 217 KiB |
BIN
app/yneg.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
app/ypos.png
Normal file
After Width: | Height: | Size: 127 KiB |
BIN
app/zneg.png
Normal file
After Width: | Height: | Size: 205 KiB |
BIN
app/zpos.png
Normal file
After Width: | Height: | Size: 197 KiB |
@ -4,6 +4,7 @@
|
||||
#include "global.hpp"
|
||||
#include <stdexcept>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
@ -18,6 +19,13 @@ namespace GL
|
||||
};
|
||||
|
||||
void init(GLenum target, GLsizei size, GLuint flags, const void *initial_data = nullptr, GLuint index = 0);
|
||||
|
||||
template<typename T>
|
||||
typename std::enable_if<sizeof(typename T::value_type) != 0, void>::type init(GLenum target, const T& t, GLuint flags, GLuint index = 0)
|
||||
{
|
||||
init(target, t.size() * sizeof(typename T::value_type), flags, t.data(), index);
|
||||
}
|
||||
|
||||
void reset() override;
|
||||
void destroyed() override;
|
||||
|
||||
|
117
gl/global.cpp
@ -48,12 +48,17 @@ namespace GL
|
||||
|
||||
void ContextManager::register_listener(ContextListener *listener)
|
||||
{
|
||||
ListenerState state{};
|
||||
state.listener = listener;
|
||||
state.id = context_id++;
|
||||
#ifdef GL_DEBUG
|
||||
cerr << "Registering listener: " <<
|
||||
static_cast<void*>(listener) << endl;
|
||||
#endif
|
||||
|
||||
auto state = make_shared<ListenerState>();
|
||||
state->listener = listener;
|
||||
state->id = context_id++;
|
||||
if (alive)
|
||||
state.reset_chain();
|
||||
listeners.push_back(std::move(state));
|
||||
state->reset_chain();
|
||||
listeners.push_back(move(state));
|
||||
}
|
||||
|
||||
void ContextManager::register_dependency(ContextListener *master, ContextListener *slave)
|
||||
@ -61,15 +66,28 @@ namespace GL
|
||||
if (!master || !slave)
|
||||
return;
|
||||
|
||||
auto& itr_master = find_or_throw(listeners, *master);
|
||||
auto& itr_slave = find_or_throw(listeners, *slave);
|
||||
itr_master.dependencies.push_back(&itr_slave);
|
||||
itr_slave.dependers.push_back(&itr_master);
|
||||
#ifdef GL_DEBUG
|
||||
cerr << "Registering dependency: " <<
|
||||
static_cast<void*>(master) << " < " << static_cast<void*>(slave) << endl;
|
||||
#endif
|
||||
|
||||
auto pred_master = [master](const shared_ptr<ListenerState>& state) {
|
||||
return state->listener == master;
|
||||
};
|
||||
|
||||
auto pred_slave = [slave](const shared_ptr<ListenerState>& state) {
|
||||
return state->listener == slave;
|
||||
};
|
||||
|
||||
auto& itr_master = find_if_or_throw(listeners, pred_master);
|
||||
auto& itr_slave = find_if_or_throw(listeners, pred_slave);
|
||||
itr_master->dependencies.push_back(itr_slave);
|
||||
itr_slave->dependers.push_back(itr_master);
|
||||
|
||||
if (alive)
|
||||
{
|
||||
itr_master.reset_chain();
|
||||
itr_slave.reset_chain();
|
||||
itr_master->reset_chain();
|
||||
itr_slave->reset_chain();
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,24 +96,59 @@ namespace GL
|
||||
if (!master_ptr || !slave_ptr)
|
||||
return;
|
||||
|
||||
auto& itr_master = find_or_throw(listeners, *master_ptr);
|
||||
auto& itr_slave = find_or_throw(listeners, *slave_ptr);
|
||||
erase_all(itr_master.dependencies, &itr_slave);
|
||||
erase_all(itr_slave.dependers, &itr_master);
|
||||
#ifdef GL_DEBUG
|
||||
cerr << "Unregistering dependency: " <<
|
||||
static_cast<void*>(master_ptr) << " < " << static_cast<void*>(slave_ptr) << endl;
|
||||
#endif
|
||||
|
||||
auto pred_master = [master_ptr](const shared_ptr<ListenerState>& state) {
|
||||
return state->listener == master_ptr;
|
||||
};
|
||||
|
||||
auto pred_slave = [slave_ptr](const shared_ptr<ListenerState>& state) {
|
||||
return state->listener == slave_ptr;
|
||||
};
|
||||
|
||||
auto& itr_master = find_if_or_throw(listeners, pred_master);
|
||||
auto& itr_slave = find_if_or_throw(listeners, pred_slave);
|
||||
|
||||
auto pred_master_erase = [&itr_master](const weak_ptr<ListenerState>& state) {
|
||||
return state.lock() == itr_master;
|
||||
};
|
||||
|
||||
auto pred_slave_erase = [&itr_slave](const weak_ptr<ListenerState>& state) {
|
||||
return state.lock() == itr_slave;
|
||||
};
|
||||
|
||||
erase_if_all(itr_master->dependencies, pred_slave_erase);
|
||||
erase_if_all(itr_slave->dependers, pred_master_erase);
|
||||
}
|
||||
|
||||
void ContextManager::unregister_listener(const ContextListener *listener)
|
||||
{
|
||||
auto& itr = find_or_throw(listeners, *listener);
|
||||
for (auto& parent_listener : itr.dependers)
|
||||
erase_all(parent_listener->dependencies, &itr);
|
||||
for (auto& child_listener : itr.dependencies)
|
||||
erase_all(child_listener->dependers, &itr);
|
||||
#ifdef GL_DEBUG
|
||||
cerr << "Unregistering listener: " <<
|
||||
static_cast<const void*>(listener) << endl;
|
||||
#endif
|
||||
|
||||
if (itr.signaled)
|
||||
auto pred = [listener](const weak_ptr<ListenerState>& state) {
|
||||
return shared_ptr<ListenerState>(state)->listener == listener;
|
||||
};
|
||||
|
||||
auto& itr = find_if_or_throw(listeners, pred);
|
||||
auto itr_pred = [&itr](const weak_ptr<ListenerState>& state) {
|
||||
return state.lock() == itr;
|
||||
};
|
||||
|
||||
for (auto& parent_listener : itr->dependers)
|
||||
erase_if_all(parent_listener.lock()->dependencies, itr_pred);
|
||||
for (auto& child_listener : itr->dependencies)
|
||||
erase_if_all(child_listener.lock()->dependers, itr_pred);
|
||||
|
||||
if (itr->signaled)
|
||||
{
|
||||
itr.signaled = false;
|
||||
itr.listener->destroyed();
|
||||
itr->signaled = false;
|
||||
itr->listener->destroyed();
|
||||
}
|
||||
|
||||
erase_all(listeners, itr);
|
||||
@ -105,13 +158,13 @@ namespace GL
|
||||
{
|
||||
alive = true;
|
||||
for (auto& state : listeners)
|
||||
state.reset_chain();
|
||||
state->reset_chain();
|
||||
}
|
||||
|
||||
void ContextManager::notify_destroyed()
|
||||
{
|
||||
for (auto& state : listeners)
|
||||
state.destroy_chain();
|
||||
state->destroy_chain();
|
||||
alive = false;
|
||||
}
|
||||
|
||||
@ -121,7 +174,12 @@ namespace GL
|
||||
{
|
||||
signaled = true;
|
||||
for (auto state : dependencies)
|
||||
state->reset_chain();
|
||||
state.lock()->reset_chain();
|
||||
|
||||
#ifdef GL_DEBUG
|
||||
cerr << "Resetting: " <<
|
||||
static_cast<void*>(listener) << endl;
|
||||
#endif
|
||||
listener->reset();
|
||||
}
|
||||
}
|
||||
@ -132,7 +190,12 @@ namespace GL
|
||||
{
|
||||
signaled = false;
|
||||
for (auto state : dependers)
|
||||
state->destroy_chain();
|
||||
state.lock()->destroy_chain();
|
||||
|
||||
#ifdef GL_DEBUG
|
||||
cerr << "Destroying: " <<
|
||||
static_cast<void*>(listener) << endl;
|
||||
#endif
|
||||
listener->destroyed();
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,10 @@
|
||||
|
||||
#include "util.hpp"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <glm/gtc/matrix_transform.hpp>
|
||||
#include <glm/gtc/type_ptr.hpp>
|
||||
|
||||
namespace GL
|
||||
{
|
||||
class LibretroGLApplication
|
||||
@ -101,10 +105,10 @@ namespace GL
|
||||
|
||||
struct ListenerState
|
||||
{
|
||||
ContextListener *listener;
|
||||
ContextListener *listener = nullptr;
|
||||
bool signaled = false;
|
||||
std::vector<ListenerState*> dependencies;
|
||||
std::vector<ListenerState*> dependers;
|
||||
std::vector<std::weak_ptr<ListenerState>> dependencies;
|
||||
std::vector<std::weak_ptr<ListenerState>> dependers;
|
||||
uint64_t id = 0;
|
||||
|
||||
void reset_chain();
|
||||
@ -116,7 +120,7 @@ namespace GL
|
||||
bool operator!=(const ContextListener& other) const { return listener != &other; }
|
||||
};
|
||||
|
||||
std::vector<ListenerState> listeners;
|
||||
std::vector<std::shared_ptr<ListenerState>> listeners;
|
||||
bool alive = false;
|
||||
|
||||
uint64_t context_id = 0;
|
||||
|
20
skybox.fs
@ -1,10 +1,26 @@
|
||||
uniform GlobalFragmentData
|
||||
{
|
||||
vec4 camera_pos;
|
||||
vec4 light_pos;
|
||||
vec4 light_color;
|
||||
vec4 light_ambient;
|
||||
};
|
||||
|
||||
uniform samplerCube uSampler1;
|
||||
uniform samplerCube uSampler0;
|
||||
|
||||
in vec3 vDirection;
|
||||
out vec4 FragColor;
|
||||
|
||||
float saturate(float a)
|
||||
{
|
||||
return clamp(a, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor = texture(uSampler1, normalize(vDirection));
|
||||
vec3 dir = normalize(vDirection);
|
||||
vec4 col = texture(uSampler0, dir);
|
||||
vec3 to_light = light_pos.xyz - camera_pos.xyz;
|
||||
col += pow(saturate(dot(dir, normalize(to_light))), 200.0 * length(to_light));
|
||||
FragColor = col;
|
||||
}
|
||||
|
54
test.fs
@ -1,40 +1,46 @@
|
||||
uniform GlobalVertexData
|
||||
uniform GlobalFragmentData
|
||||
{
|
||||
mat4 vp;
|
||||
mat4 view;
|
||||
mat4 view_nt;
|
||||
mat4 proj;
|
||||
mat4 inv_vp;
|
||||
mat4 inv_view;
|
||||
mat4 inv_view_nt;
|
||||
mat4 inv_proj;
|
||||
vec4 camera_pos;
|
||||
vec4 light_pos;
|
||||
vec4 light_color;
|
||||
vec4 light_ambient;
|
||||
};
|
||||
|
||||
in vec2 vTex;
|
||||
in vec3 vWorldPos;
|
||||
in vec3 vNormal;
|
||||
|
||||
uniform sampler2D uSampler0;
|
||||
uniform samplerCube uSampler1;
|
||||
uniform samplerCube uSampler0;
|
||||
|
||||
out vec4 FragColor;
|
||||
|
||||
float saturate(float a)
|
||||
{
|
||||
return clamp(a, 0.0, 1.0);
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
vec3 to_plane = normalize(vWorldPos - camera_pos.xyz);
|
||||
vec3 normal = vec3(0.02 * sin(vWorldPos.x * 0.15), 0.01 * cos(vWorldPos.y * 0.29), 1.0);
|
||||
normal = normalize(normal);
|
||||
vec3 reflect_dir = reflect(to_plane, normal);
|
||||
vec4 col_reflect = texture(uSampler1, reflect_dir);
|
||||
vec3 vEye = normalize(camera_pos.xyz - vWorldPos);
|
||||
vec3 vLight = normalize(light_pos.xyz - vWorldPos);
|
||||
vec3 normal = normalize(vNormal);
|
||||
|
||||
float fres = 1.0;
|
||||
vec3 refract_dir = refract(to_plane, normal, 1.4);
|
||||
vec4 col_refract = vec4(0.0);
|
||||
if (refract_dir != vec3(0.0))
|
||||
float ndotl = saturate(dot(vLight, normal));
|
||||
float spec = 0.0;
|
||||
if (ndotl > 0.0)
|
||||
{
|
||||
col_refract = texture(uSampler1, refract_dir);
|
||||
fres = pow(1.0 - dot(refract_dir, -normal), 5.0);
|
||||
vec3 half_vec = normalize(vEye + vLight);
|
||||
spec = pow(saturate(dot(half_vec, normal)), 50.0);
|
||||
}
|
||||
|
||||
FragColor = mix(col_refract, col_reflect, fres);
|
||||
vec3 refract_normal = refract(-vEye, normal, 1.4);
|
||||
vec3 reflect_normal = reflect(-vEye, normal);
|
||||
|
||||
float incidence = 0.0;
|
||||
incidence = dot(refract_normal, -normal);
|
||||
|
||||
vec4 refracted = texture(uSampler0, refract_normal);
|
||||
vec4 reflected = texture(uSampler0, reflect_normal);
|
||||
|
||||
vec4 col = light_ambient + light_color * spec;
|
||||
FragColor = mix(reflected, refracted, incidence) + col * vec4(1.1, 0.8, 0.7, 1.0);
|
||||
}
|
||||
|
14
test.vs
@ -11,18 +11,22 @@ uniform GlobalVertexData
|
||||
vec4 camera_pos;
|
||||
};
|
||||
|
||||
in vec2 aVertex;
|
||||
in vec2 aTexCoord;
|
||||
uniform VertexSlot1
|
||||
{
|
||||
mat4 model;
|
||||
};
|
||||
|
||||
in vec3 aVertex;
|
||||
in vec3 aNormal;
|
||||
|
||||
out vec2 vTex;
|
||||
out vec3 vWorldPos;
|
||||
out vec3 vNormal;
|
||||
|
||||
void main()
|
||||
{
|
||||
vec4 world = vec4(aVertex.x - 64.0, aVertex.y - 64.0, -10.0, 1.0);
|
||||
vec4 world = model * vec4(aVertex, 1.0);
|
||||
gl_Position = vp * world;
|
||||
vTex = vec2(1.0, -1.0) * aVertex / 128.0;
|
||||
vWorldPos = world.xyz;
|
||||
vNormal = mat3(model) * aNormal;
|
||||
}
|
||||
|
||||
|
27
util.hpp
@ -12,6 +12,16 @@
|
||||
#include <algorithm>
|
||||
#include <cstdarg>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
|
||||
namespace Util
|
||||
{
|
||||
template<typename T, typename... P>
|
||||
inline std::unique_ptr<T> make_unique(P&&... p)
|
||||
{
|
||||
return std::unique_ptr<T>(new T(std::forward<P>(p)...));
|
||||
}
|
||||
}
|
||||
|
||||
namespace Template
|
||||
{
|
||||
@ -24,10 +34,25 @@ namespace Template
|
||||
return *itr;
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
inline auto find_if_or_throw(T& t, const P& pred) -> decltype(*std::begin(t))
|
||||
{
|
||||
auto itr = std::find_if(std::begin(t), std::end(t), pred);
|
||||
if (itr == std::end(t))
|
||||
throw std::runtime_error("Couldn't find element in iterator.");
|
||||
return *itr;
|
||||
}
|
||||
|
||||
template<typename T, typename P>
|
||||
inline void erase_if_all(T& t, const P& p)
|
||||
{
|
||||
t.erase(std::remove_if(std::begin(t), std::end(t), p), std::end(t));
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
inline void erase_all(T& t, const U& u)
|
||||
{
|
||||
t.erase(std::remove_if(std::begin(t), std::end(t), [&u](const U& other) { return other == u; }), std::end(t));
|
||||
erase_if_all(t, [&u](const U& other) { return other == u; });
|
||||
}
|
||||
}
|
||||
|
||||
|