2015-07-04 15:22:28 +02:00
|
|
|
#include "pipeline.h"
|
|
|
|
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/pipeline.h"
|
2014-05-20 23:35:09 +02:00
|
|
|
#include "core/crc32.h"
|
2014-10-15 22:16:03 +02:00
|
|
|
#include "core/frustum.h"
|
2015-05-16 02:24:15 +02:00
|
|
|
#include "core/fs/ifile.h"
|
2014-05-20 23:35:09 +02:00
|
|
|
#include "core/fs/file_system.h"
|
2015-02-27 23:56:06 +01:00
|
|
|
#include "core/lifo_allocator.h"
|
2014-06-03 21:46:34 +02:00
|
|
|
#include "core/log.h"
|
2015-08-11 23:55:58 +02:00
|
|
|
#include "core/lua_wrapper.h"
|
2014-08-10 23:40:22 +02:00
|
|
|
#include "core/profiler.h"
|
2015-08-12 21:54:47 +02:00
|
|
|
#include "core/static_array.h"
|
2015-08-11 23:55:58 +02:00
|
|
|
#include "engine.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/frame_buffer.h"
|
|
|
|
#include "renderer/material.h"
|
2016-01-12 13:52:14 +01:00
|
|
|
#include "renderer/material_manager.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/model.h"
|
2015-11-04 22:43:54 +01:00
|
|
|
#include "renderer/particle_system.h"
|
2015-10-06 17:00:52 +02:00
|
|
|
#include "renderer/pose.h"
|
2016-02-09 00:29:15 +01:00
|
|
|
#include "renderer/render_scene.h"
|
2015-08-17 23:45:26 +02:00
|
|
|
#include "renderer/renderer.h"
|
|
|
|
#include "renderer/shader.h"
|
|
|
|
#include "renderer/terrain.h"
|
|
|
|
#include "renderer/texture.h"
|
|
|
|
#include "renderer/transient_geometry.h"
|
2015-07-30 09:18:37 +02:00
|
|
|
#include "universe/universe.h"
|
2015-10-01 02:07:22 +02:00
|
|
|
#include <bgfx/bgfx.h>
|
2015-11-13 16:52:42 +01:00
|
|
|
#include <cmath>
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2015-07-04 15:22:28 +02:00
|
|
|
|
|
|
|
namespace Lumix
|
|
|
|
{
|
|
|
|
|
|
|
|
|
2015-10-18 11:53:32 +02:00
|
|
|
static const float SHADOW_CAM_NEAR = 50.0f;
|
|
|
|
static const float SHADOW_CAM_FAR = 5000.0f;
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
struct InstanceData
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-01-25 14:07:12 +01:00
|
|
|
static const int MAX_INSTANCE_COUNT = 128;
|
2015-07-05 15:58:53 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
const bgfx::InstanceDataBuffer* buffer;
|
|
|
|
int instance_count;
|
|
|
|
Mesh* mesh;
|
|
|
|
Model* model;
|
2015-07-23 23:17:51 +02:00
|
|
|
};
|
2015-07-05 15:58:53 +02:00
|
|
|
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2016-01-24 17:20:03 +01:00
|
|
|
struct TextureBindData
|
|
|
|
{
|
|
|
|
bgfx::TextureHandle texture;
|
|
|
|
bgfx::UniformHandle uniform;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-01-22 18:12:59 +01:00
|
|
|
struct DirectionalLightUniforms
|
|
|
|
{
|
|
|
|
Vec4 diffuse_light_color;
|
|
|
|
Vec4 ambient_light_color;
|
|
|
|
Vec4 light_dir_fov;
|
|
|
|
Vec4 fog_color_density;
|
|
|
|
Vec4 fog_params;
|
2016-01-28 21:44:35 +01:00
|
|
|
Vec4 specular;
|
2016-01-22 18:12:59 +01:00
|
|
|
};
|
|
|
|
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
struct PipelineImpl : public Pipeline
|
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
PipelineImpl(Renderer& renderer, const Path& path, IAllocator& allocator)
|
|
|
|
: m_allocator(allocator)
|
|
|
|
, m_path(path)
|
2015-07-23 23:17:51 +02:00
|
|
|
, m_framebuffers(allocator)
|
|
|
|
, m_lua_state(nullptr)
|
2015-11-10 22:25:36 +01:00
|
|
|
, m_parameters(allocator)
|
2016-01-12 13:52:14 +01:00
|
|
|
, m_custom_commands_handlers(allocator)
|
|
|
|
, m_tmp_terrains(allocator)
|
|
|
|
, m_tmp_grasses(allocator)
|
|
|
|
, m_tmp_meshes(allocator)
|
2016-01-24 17:20:03 +01:00
|
|
|
, m_tmp_local_lights(allocator)
|
2016-01-12 13:52:14 +01:00
|
|
|
, m_uniforms(allocator)
|
|
|
|
, m_renderer(renderer)
|
|
|
|
, m_default_framebuffer(nullptr)
|
|
|
|
, m_debug_line_material(nullptr)
|
|
|
|
, m_debug_flags(BGFX_DEBUG_TEXT)
|
|
|
|
, m_point_light_shadowmaps(allocator)
|
|
|
|
, m_materials(allocator)
|
|
|
|
, m_is_rendering_in_shadowmap(false)
|
|
|
|
, m_is_ready(false)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2016-01-24 17:20:03 +01:00
|
|
|
m_deferred_point_light_vertex_decl.begin()
|
|
|
|
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
|
|
|
|
.end();
|
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
m_base_vertex_decl.begin()
|
|
|
|
.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float)
|
|
|
|
.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true)
|
|
|
|
.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float)
|
|
|
|
.end();
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
m_is_wireframe = false;
|
|
|
|
m_view_x = m_view_y = 0;
|
|
|
|
m_has_shadowmap_define_idx = m_renderer.getShaderDefineIdx("HAS_SHADOWMAP");
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
createUniforms();
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
m_debug_line_material = static_cast<Material*>(
|
2016-01-24 17:20:03 +01:00
|
|
|
renderer.getMaterialManager().load(Lumix::Path("shaders/debug_line.mat")));
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
m_scene = nullptr;
|
|
|
|
m_width = m_height = -1;
|
2015-10-03 01:14:38 +02:00
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
createParticleBuffers();
|
2016-01-26 10:27:31 +01:00
|
|
|
createCubeBuffers();
|
2016-01-28 15:19:56 +01:00
|
|
|
m_stats = {};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const Stats& getStats() override
|
|
|
|
{
|
|
|
|
return m_stats;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-05-20 23:35:09 +02:00
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void parseRenderbuffers(lua_State* L, FrameBuffer::Declaration& decl)
|
|
|
|
{
|
|
|
|
decl.m_renderbuffers_count = 0;
|
|
|
|
int len = (int)lua_rawlen(L, -1);
|
|
|
|
for (int i = 0; i < len; ++i)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
if (lua_rawgeti(L, -1, 1 + i) == LUA_TTABLE)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
FrameBuffer::RenderBuffer& buf =
|
|
|
|
decl.m_renderbuffers[decl.m_renderbuffers_count];
|
|
|
|
buf.parse(L);
|
|
|
|
++decl.m_renderbuffers_count;
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
lua_pop(L, 1);
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2015-05-16 13:17:20 +02:00
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void parseParameters(lua_State* L)
|
|
|
|
{
|
|
|
|
m_parameters.clear();
|
|
|
|
if (lua_getglobal(L, "parameters") == LUA_TTABLE)
|
|
|
|
{
|
|
|
|
lua_pushnil(L);
|
|
|
|
while (lua_next(L, -2) != 0)
|
|
|
|
{
|
|
|
|
const char* parameter_name = luaL_checkstring(L, -2);
|
|
|
|
m_parameters.push(Lumix::string(parameter_name, m_allocator));
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void parseFramebuffers(lua_State* L)
|
|
|
|
{
|
|
|
|
if (lua_getglobal(L, "framebuffers") == LUA_TTABLE)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
for(int i = 0; i < m_framebuffers.size(); ++i)
|
|
|
|
{
|
|
|
|
LUMIX_DELETE(m_allocator, m_framebuffers[i]);
|
|
|
|
}
|
|
|
|
m_framebuffers.clear();
|
|
|
|
|
2015-05-16 13:17:20 +02:00
|
|
|
int len = (int)lua_rawlen(L, -1);
|
2016-01-12 13:52:14 +01:00
|
|
|
ASSERT(m_framebuffers.empty());
|
2015-05-16 13:17:20 +02:00
|
|
|
for (int i = 0; i < len; ++i)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2015-05-16 13:17:20 +02:00
|
|
|
if (lua_rawgeti(L, -1, 1 + i) == LUA_TTABLE)
|
2014-12-30 13:21:23 +01:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
FrameBuffer::Declaration decl;
|
2015-07-23 23:17:51 +02:00
|
|
|
if (lua_getfield(L, -1, "name") == LUA_TSTRING)
|
|
|
|
{
|
2016-01-22 23:33:14 +01:00
|
|
|
copyString(decl.m_name, sizeof(decl.m_name), lua_tostring(L, -1));
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
if (lua_getfield(L, -1, "width") == LUA_TNUMBER)
|
2015-05-16 13:17:20 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
decl.m_width = (int)lua_tointeger(L, -1);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
2016-02-01 16:38:27 +01:00
|
|
|
if (lua_getfield(L, -1, "size_ratio") == LUA_TBOOLEAN)
|
|
|
|
{
|
|
|
|
decl.m_size_ratio = LuaWrapper::toType<Vec2>(L, -1);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
2016-01-22 23:33:14 +01:00
|
|
|
if (lua_getfield(L, -1, "screen_size") == LUA_TBOOLEAN)
|
|
|
|
{
|
2016-02-01 16:38:27 +01:00
|
|
|
bool is_screen_size = lua_toboolean(L, -1) != 0;
|
|
|
|
decl.m_size_ratio = is_screen_size ? Vec2(1, 1) : Vec2(-1, -1);
|
2016-01-22 23:33:14 +01:00
|
|
|
}
|
2016-01-26 01:59:51 +01:00
|
|
|
else
|
|
|
|
{
|
2016-02-01 16:38:27 +01:00
|
|
|
decl.m_size_ratio = Vec2(-1, -1);
|
2016-01-26 01:59:51 +01:00
|
|
|
}
|
2016-01-22 23:33:14 +01:00
|
|
|
lua_pop(L, 1);
|
2015-07-23 23:17:51 +02:00
|
|
|
if (lua_getfield(L, -1, "height") == LUA_TNUMBER)
|
|
|
|
{
|
|
|
|
decl.m_height = (int)lua_tointeger(L, -1);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
if (lua_getfield(L, -1, "renderbuffers") == LUA_TTABLE)
|
|
|
|
{
|
|
|
|
parseRenderbuffers(L, decl);
|
2015-05-16 13:17:20 +02:00
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
2016-01-12 13:52:14 +01:00
|
|
|
auto* fb = LUMIX_NEW(m_allocator, FrameBuffer)(decl);
|
|
|
|
m_framebuffers.push(fb);
|
2016-01-12 19:37:00 +01:00
|
|
|
if (compareString(decl.m_name, "default") == 0) m_default_framebuffer = fb;
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
lua_pop(L, 1);
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
2015-05-16 13:17:20 +02:00
|
|
|
|
|
|
|
|
2016-02-10 00:00:21 +01:00
|
|
|
void registerConst(const char* name, uint32 value)
|
|
|
|
{
|
|
|
|
lua_pushinteger(m_lua_state, value);
|
|
|
|
lua_setglobal(m_lua_state, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void registerCFunction(const char* name, lua_CFunction function)
|
|
|
|
{
|
|
|
|
lua_pushcfunction(m_lua_state, function);
|
|
|
|
lua_setglobal(m_lua_state, name);
|
|
|
|
}
|
2014-12-30 13:21:23 +01:00
|
|
|
|
2015-05-16 13:17:20 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void registerCFunctions();
|
2015-05-16 13:17:20 +02:00
|
|
|
|
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
void load() override
|
|
|
|
{
|
|
|
|
auto& fs = m_renderer.getEngine().getFileSystem();
|
|
|
|
Delegate<void(FS::IFile&, bool)> cb;
|
|
|
|
cb.bind<PipelineImpl, &PipelineImpl::onFileLoaded>(this);
|
|
|
|
fs.openAsync(fs.getDefaultDevice(), m_path, FS::Mode::OPEN_AND_READ, cb);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void onFileLoaded(FS::IFile& file, bool success)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
if(!success) return;
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
if (m_lua_state)
|
|
|
|
{
|
|
|
|
lua_close(m_lua_state);
|
|
|
|
m_lua_state = nullptr;
|
|
|
|
}
|
2015-10-03 01:14:38 +02:00
|
|
|
m_lua_state = luaL_newstate();
|
|
|
|
luaL_openlibs(m_lua_state);
|
|
|
|
bool errors =
|
2015-10-18 11:53:32 +02:00
|
|
|
luaL_loadbuffer(
|
2016-01-12 13:52:14 +01:00
|
|
|
m_lua_state, (const char*)file.getBuffer(), file.size(), m_path.c_str()) !=
|
2015-10-18 11:53:32 +02:00
|
|
|
LUA_OK;
|
2015-10-03 01:14:38 +02:00
|
|
|
errors = errors || lua_pcall(m_lua_state, 0, LUA_MULTRET, 0) != LUA_OK;
|
|
|
|
if (errors)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
g_log_error.log("lua") << m_path.c_str() << ": " << lua_tostring(m_lua_state, -1);
|
2015-10-03 01:14:38 +02:00
|
|
|
lua_pop(m_lua_state, 1);
|
2016-01-12 13:52:14 +01:00
|
|
|
return;
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
2015-10-03 01:14:38 +02:00
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
parseParameters(m_lua_state);
|
2015-10-03 01:14:38 +02:00
|
|
|
parseFramebuffers(m_lua_state);
|
|
|
|
registerCFunctions();
|
2016-01-12 13:52:14 +01:00
|
|
|
|
|
|
|
m_width = m_height = -1;
|
|
|
|
if (lua_getglobal(m_lua_state, "init") == LUA_TFUNCTION)
|
|
|
|
{
|
|
|
|
lua_pushlightuserdata(m_lua_state, this);
|
|
|
|
if (lua_pcall(m_lua_state, 1, 0, 0) != LUA_OK)
|
|
|
|
{
|
|
|
|
g_log_error.log("lua") << lua_tostring(m_lua_state, -1);
|
|
|
|
lua_pop(m_lua_state, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
lua_pop(m_lua_state, 1);
|
|
|
|
}
|
|
|
|
m_is_ready = true;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
lua_State* m_lua_state;
|
2015-11-10 22:25:36 +01:00
|
|
|
Array<string> m_parameters;
|
2016-01-28 15:19:56 +01:00
|
|
|
Stats m_stats;
|
2015-11-04 22:43:54 +01:00
|
|
|
|
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
int getParameterCount() const override
|
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
return m_parameters.size();
|
2015-11-10 22:25:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const char* getParameterName(int index) const override
|
|
|
|
{
|
2016-02-05 14:32:21 +01:00
|
|
|
if (index >= m_parameters.size()) return nullptr;
|
2016-01-12 13:52:14 +01:00
|
|
|
return m_parameters[index].c_str();
|
2015-11-10 22:25:36 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool getParameter(int index) override
|
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
if (!m_lua_state) return false;
|
|
|
|
if (index >= m_parameters.size()) return false;
|
2015-11-10 22:25:36 +01:00
|
|
|
|
|
|
|
bool ret = false;
|
2016-01-12 13:52:14 +01:00
|
|
|
lua_State* L = m_lua_state;
|
2015-11-10 22:25:36 +01:00
|
|
|
if (lua_getglobal(L, "parameters") == LUA_TTABLE)
|
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
lua_getfield(L, -1, m_parameters[index].c_str());
|
2015-11-10 22:25:36 +01:00
|
|
|
ret = lua_toboolean(L, -1) != 0;
|
|
|
|
lua_pop(L, -1);
|
|
|
|
}
|
|
|
|
lua_pop(L, -1);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setParameter(int index, bool value) override
|
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
if (!m_lua_state) return;
|
|
|
|
if (index >= m_parameters.size()) return;
|
2015-11-10 22:25:36 +01:00
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
lua_State* L = m_lua_state;
|
2015-11-10 22:25:36 +01:00
|
|
|
if (lua_getglobal(L, "parameters") == LUA_TTABLE)
|
|
|
|
{
|
|
|
|
lua_pushboolean(L, value);
|
2016-01-12 13:52:14 +01:00
|
|
|
lua_setfield(L, -2, m_parameters[index].c_str());
|
2015-11-10 22:25:36 +01:00
|
|
|
}
|
|
|
|
lua_pop(L, -1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-04 22:43:54 +01:00
|
|
|
void createParticleBuffers()
|
|
|
|
{
|
|
|
|
BaseVertex vertices[] = {
|
|
|
|
{ -1, -1, 1, 0xffffffff, 0, 0},
|
|
|
|
{ -1, 1, 1, 0xffffffff, 0, 1},
|
|
|
|
{ 1, 1, 1, 0xffffffff, 1, 1},
|
|
|
|
{ 1, -1, 1, 0xffffffff, 1, 0},
|
|
|
|
};
|
|
|
|
|
|
|
|
const bgfx::Memory* vertex_mem = bgfx::copy(vertices, sizeof(vertices));
|
|
|
|
m_particle_vertex_buffer = bgfx::createVertexBuffer(vertex_mem, m_base_vertex_decl);
|
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
uint16 indices[] = { 0, 1, 2, 0, 2, 3 };
|
2015-11-04 22:43:54 +01:00
|
|
|
const bgfx::Memory* index_mem = bgfx::copy(indices, sizeof(indices));
|
|
|
|
m_particle_index_buffer = bgfx::createIndexBuffer(index_mem);
|
2015-10-24 15:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void createUniforms()
|
|
|
|
{
|
2015-11-01 12:00:10 +01:00
|
|
|
m_texture_size_uniform = bgfx::createUniform("u_textureSize", bgfx::UniformType::Vec4);
|
2016-02-01 15:13:00 +01:00
|
|
|
m_cam_params = bgfx::createUniform("u_camParams", bgfx::UniformType::Vec4);
|
|
|
|
m_cam_proj_uniform = bgfx::createUniform("u_camProj", bgfx::UniformType::Mat4);
|
2015-10-05 22:44:03 +02:00
|
|
|
m_cam_view_uniform = bgfx::createUniform("u_camView", bgfx::UniformType::Mat4);
|
2016-02-01 15:13:00 +01:00
|
|
|
m_cam_inv_view_uniform = bgfx::createUniform("u_camInView", bgfx::UniformType::Mat4);
|
2016-01-24 17:20:03 +01:00
|
|
|
m_cam_inv_viewproj_uniform = bgfx::createUniform("u_camInvViewProj", bgfx::UniformType::Mat4);
|
2015-10-05 22:44:03 +02:00
|
|
|
m_cam_inv_proj_uniform = bgfx::createUniform("u_camInvProj", bgfx::UniformType::Mat4);
|
|
|
|
m_tex_shadowmap_uniform = bgfx::createUniform("u_texShadowmap", bgfx::UniformType::Int1);
|
|
|
|
m_terrain_scale_uniform = bgfx::createUniform("u_terrainScale", bgfx::UniformType::Vec4);
|
|
|
|
m_rel_camera_pos_uniform = bgfx::createUniform("u_relCamPos", bgfx::UniformType::Vec4);
|
|
|
|
m_terrain_params_uniform = bgfx::createUniform("u_terrainParams", bgfx::UniformType::Vec4);
|
2015-10-17 00:18:47 +02:00
|
|
|
m_fog_params_uniform = bgfx::createUniform("u_fogParams", bgfx::UniformType::Vec4);
|
2015-07-23 23:17:51 +02:00
|
|
|
m_fog_color_density_uniform =
|
|
|
|
bgfx::createUniform("u_fogColorDensity", bgfx::UniformType::Vec4);
|
|
|
|
m_light_pos_radius_uniform =
|
|
|
|
bgfx::createUniform("u_lightPosRadius", bgfx::UniformType::Vec4);
|
2016-01-26 13:21:56 +01:00
|
|
|
m_light_color_attenuation_uniform = bgfx::createUniform("u_lightRgbAttenuation", bgfx::UniformType::Vec4);
|
2015-10-05 22:44:03 +02:00
|
|
|
m_light_dir_fov_uniform = bgfx::createUniform("u_lightDirFov", bgfx::UniformType::Vec4);
|
2015-07-23 23:17:51 +02:00
|
|
|
m_light_specular_uniform =
|
|
|
|
bgfx::createUniform("u_lightSpecular", bgfx::UniformType::Mat4, 64);
|
2015-10-05 22:44:03 +02:00
|
|
|
m_ambient_color_uniform = bgfx::createUniform("u_ambientColor", bgfx::UniformType::Vec4);
|
|
|
|
m_shadowmap_matrices_uniform =
|
|
|
|
bgfx::createUniform("u_shadowmapMatrices", bgfx::UniformType::Mat4, 4);
|
2015-07-23 23:17:51 +02:00
|
|
|
m_bone_matrices_uniform =
|
|
|
|
bgfx::createUniform("u_boneMatrices", bgfx::UniformType::Mat4, 64);
|
2015-10-05 22:44:03 +02:00
|
|
|
m_specular_shininess_uniform =
|
|
|
|
bgfx::createUniform("u_materialSpecularShininess", bgfx::UniformType::Vec4);
|
|
|
|
m_terrain_matrix_uniform = bgfx::createUniform("u_terrainMatrix", bgfx::UniformType::Mat4);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
void destroyUniforms()
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-09-05 13:08:47 +02:00
|
|
|
bgfx::destroyUniform(m_tex_shadowmap_uniform);
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::destroyUniform(m_terrain_matrix_uniform);
|
|
|
|
bgfx::destroyUniform(m_specular_shininess_uniform);
|
|
|
|
bgfx::destroyUniform(m_bone_matrices_uniform);
|
|
|
|
bgfx::destroyUniform(m_terrain_scale_uniform);
|
|
|
|
bgfx::destroyUniform(m_rel_camera_pos_uniform);
|
2015-08-24 21:00:35 +02:00
|
|
|
bgfx::destroyUniform(m_terrain_params_uniform);
|
2015-10-17 00:18:47 +02:00
|
|
|
bgfx::destroyUniform(m_fog_params_uniform);
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::destroyUniform(m_fog_color_density_uniform);
|
|
|
|
bgfx::destroyUniform(m_light_pos_radius_uniform);
|
2016-01-26 13:21:56 +01:00
|
|
|
bgfx::destroyUniform(m_light_color_attenuation_uniform);
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::destroyUniform(m_light_dir_fov_uniform);
|
|
|
|
bgfx::destroyUniform(m_ambient_color_uniform);
|
|
|
|
bgfx::destroyUniform(m_shadowmap_matrices_uniform);
|
|
|
|
bgfx::destroyUniform(m_light_specular_uniform);
|
2015-09-11 03:58:02 +02:00
|
|
|
bgfx::destroyUniform(m_cam_inv_proj_uniform);
|
2016-01-24 17:20:03 +01:00
|
|
|
bgfx::destroyUniform(m_cam_inv_viewproj_uniform);
|
2015-09-11 03:58:02 +02:00
|
|
|
bgfx::destroyUniform(m_cam_view_uniform);
|
2016-02-01 15:13:00 +01:00
|
|
|
bgfx::destroyUniform(m_cam_proj_uniform);
|
|
|
|
bgfx::destroyUniform(m_cam_params);
|
|
|
|
bgfx::destroyUniform(m_cam_inv_view_uniform);
|
2015-11-01 12:00:10 +01:00
|
|
|
bgfx::destroyUniform(m_texture_size_uniform);
|
2015-10-24 15:27:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
~PipelineImpl()
|
2015-10-24 15:27:48 +02:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
if(m_lua_state)
|
|
|
|
{
|
|
|
|
lua_close(m_lua_state);
|
|
|
|
}
|
|
|
|
|
|
|
|
ResourceManagerBase& material_manager = m_renderer.getMaterialManager();
|
2015-10-24 15:27:48 +02:00
|
|
|
for (auto* material : m_materials)
|
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
material_manager.unload(*material);
|
2015-10-24 15:27:48 +02:00
|
|
|
}
|
2016-01-12 13:52:14 +01:00
|
|
|
material_manager.unload(*m_debug_line_material);
|
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
destroyUniforms();
|
2015-07-23 23:17:51 +02:00
|
|
|
|
|
|
|
for (int i = 0; i < m_uniforms.size(); ++i)
|
|
|
|
{
|
|
|
|
bgfx::destroyUniform(m_uniforms[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < m_framebuffers.size(); ++i)
|
|
|
|
{
|
2015-11-11 23:25:44 +01:00
|
|
|
LUMIX_DELETE(m_allocator, m_framebuffers[i]);
|
2015-09-20 20:28:51 +02:00
|
|
|
if (m_framebuffers[i] == m_default_framebuffer) m_default_framebuffer = nullptr;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-11-11 23:25:44 +01:00
|
|
|
LUMIX_DELETE(m_allocator, m_default_framebuffer);
|
2015-11-04 22:43:54 +01:00
|
|
|
|
2016-01-26 10:27:31 +01:00
|
|
|
bgfx::destroyVertexBuffer(m_cube_vb);
|
|
|
|
bgfx::destroyIndexBuffer(m_cube_ib);
|
2015-11-04 22:43:54 +01:00
|
|
|
bgfx::destroyIndexBuffer(m_particle_index_buffer);
|
|
|
|
bgfx::destroyVertexBuffer(m_particle_vertex_buffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
void renderParticlesFromEmitter(const ParticleEmitter& emitter)
|
2015-11-04 22:43:54 +01:00
|
|
|
{
|
|
|
|
static const int PARTICLE_BATCH_SIZE = 256;
|
|
|
|
|
|
|
|
if (emitter.m_life.empty()) return;
|
|
|
|
if (!emitter.getMaterial()) return;
|
|
|
|
if (!emitter.getMaterial()->isReady()) return;
|
|
|
|
|
|
|
|
Material* material = emitter.getMaterial();
|
|
|
|
|
|
|
|
const bgfx::InstanceDataBuffer* instance_buffer = nullptr;
|
|
|
|
struct Instance
|
|
|
|
{
|
|
|
|
Vec4 pos;
|
2015-11-07 13:57:11 +01:00
|
|
|
Vec4 alpha_and_rotation;
|
2015-11-04 22:43:54 +01:00
|
|
|
};
|
|
|
|
Instance* instance = nullptr;
|
|
|
|
|
|
|
|
for (int i = 0, c = emitter.m_life.size(); i < c; ++i)
|
|
|
|
{
|
|
|
|
if (i % PARTICLE_BATCH_SIZE == 0)
|
|
|
|
{
|
|
|
|
if (instance_buffer)
|
|
|
|
{
|
|
|
|
setMaterial(material);
|
|
|
|
bgfx::setInstanceDataBuffer(instance_buffer, PARTICLE_BATCH_SIZE);
|
|
|
|
bgfx::setVertexBuffer(m_particle_vertex_buffer);
|
|
|
|
bgfx::setIndexBuffer(m_particle_index_buffer);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2016-01-18 00:31:13 +01:00
|
|
|
bgfx::setState(m_render_state | material->getRenderStates());
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
m_stats.m_instance_count += PARTICLE_BATCH_SIZE;
|
|
|
|
m_stats.m_triangle_count += PARTICLE_BATCH_SIZE * 2;
|
2015-11-04 22:43:54 +01:00
|
|
|
bgfx::submit(m_view_idx, material->getShaderInstance().m_program_handles[m_pass_idx]);
|
|
|
|
}
|
|
|
|
|
|
|
|
instance_buffer = bgfx::allocInstanceDataBuffer(PARTICLE_BATCH_SIZE, sizeof(Instance));
|
|
|
|
instance = (Instance*)instance_buffer->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
instance->pos = Vec4(emitter.m_position[i], emitter.m_size[i]);
|
2015-11-07 13:57:11 +01:00
|
|
|
instance->alpha_and_rotation = Vec4(emitter.m_alpha[i], emitter.m_rotation[i], 0, 0);
|
2015-11-04 22:43:54 +01:00
|
|
|
++instance;
|
|
|
|
}
|
|
|
|
|
2016-01-17 17:14:18 +01:00
|
|
|
setMaterial(material);
|
2016-01-28 15:19:56 +01:00
|
|
|
int instance_count = emitter.m_life.size() % PARTICLE_BATCH_SIZE;
|
|
|
|
bgfx::setInstanceDataBuffer(instance_buffer, instance_count);
|
2016-01-17 17:14:18 +01:00
|
|
|
bgfx::setVertexBuffer(m_particle_vertex_buffer);
|
|
|
|
bgfx::setIndexBuffer(m_particle_index_buffer);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2016-01-17 17:14:18 +01:00
|
|
|
bgfx::setState(m_render_state | material->getRenderStates());
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
m_stats.m_instance_count += instance_count;
|
|
|
|
m_stats.m_triangle_count += instance_count * 2;
|
2016-01-17 17:14:18 +01:00
|
|
|
bgfx::submit(m_view_idx, material->getShaderInstance().m_program_handles[m_pass_idx]);
|
2015-11-04 22:43:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void renderParticles()
|
|
|
|
{
|
|
|
|
const auto& emitters = m_scene->getParticleEmitters();
|
|
|
|
for (const auto* emitter : emitters)
|
|
|
|
{
|
|
|
|
if (!emitter) continue;
|
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
renderParticlesFromEmitter(*emitter);
|
2015-11-04 22:43:54 +01:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-01-03 12:13:13 +01:00
|
|
|
|
2015-08-14 22:12:51 +02:00
|
|
|
|
2015-10-25 17:35:06 +01:00
|
|
|
void bindFramebufferTexture(const char* framebuffer_name,
|
|
|
|
int renderbuffer_idx,
|
|
|
|
int uniform_idx)
|
|
|
|
{
|
|
|
|
FrameBuffer* fb = getFramebuffer(framebuffer_name);
|
|
|
|
if (!fb) return;
|
|
|
|
|
2015-11-01 12:00:10 +01:00
|
|
|
Vec4 size;
|
|
|
|
size.x = (float)fb->getWidth();
|
|
|
|
size.y = (float)fb->getHeight();
|
2016-01-22 23:33:14 +01:00
|
|
|
if (m_bind_framebuffer_texture_idx == 0) bgfx::setUniform(m_texture_size_uniform, &size);
|
|
|
|
bgfx::setTexture(m_bind_framebuffer_texture_idx,
|
|
|
|
m_uniforms[uniform_idx],
|
|
|
|
fb->getRenderbufferHandle(renderbuffer_idx));
|
|
|
|
++m_bind_framebuffer_texture_idx;
|
2015-10-25 17:35:06 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void setViewProjection(const Matrix& mtx, int width, int height) override
|
2015-08-14 22:12:51 +02:00
|
|
|
{
|
2015-11-14 00:25:08 +01:00
|
|
|
bgfx::setViewRect(m_view_idx, 0, 0, (uint16_t)width, (uint16_t)height);
|
2015-08-14 22:12:51 +02:00
|
|
|
bgfx::setViewTransform(m_view_idx, nullptr, &mtx.m11);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void finishInstances(int idx)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2015-08-27 23:18:49 +02:00
|
|
|
InstanceData& data = m_instances_data[idx];
|
2015-12-10 20:27:51 +01:00
|
|
|
if (!data.buffer) return;
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
Mesh& mesh = *data.mesh;
|
|
|
|
const Model& model = *data.model;
|
2016-01-22 18:02:07 +01:00
|
|
|
Material* material = mesh.material;
|
|
|
|
const uint16 stride = mesh.vertex_def.getStride();
|
2015-08-27 23:18:49 +02:00
|
|
|
|
|
|
|
setMaterial(material);
|
2015-10-06 17:00:52 +02:00
|
|
|
bgfx::setVertexBuffer(model.getVerticesHandle(),
|
2016-01-22 18:02:07 +01:00
|
|
|
mesh.attribute_array_offset / stride,
|
|
|
|
mesh.attribute_array_size / stride);
|
2015-10-06 17:00:52 +02:00
|
|
|
bgfx::setIndexBuffer(model.getIndicesHandle(),
|
2016-01-22 18:02:07 +01:00
|
|
|
mesh.indices_offset,
|
|
|
|
mesh.indices_count);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2015-08-27 23:18:49 +02:00
|
|
|
bgfx::setState(m_render_state | material->getRenderStates());
|
2015-12-10 20:27:51 +01:00
|
|
|
bgfx::setInstanceDataBuffer(data.buffer, data.instance_count);
|
2016-01-22 18:02:07 +01:00
|
|
|
ShaderInstance& shader_instance = mesh.material->getShaderInstance();
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
m_stats.m_instance_count += data.instance_count;
|
|
|
|
m_stats.m_triangle_count += data.instance_count * mesh.indices_count / 3;
|
2015-08-27 23:18:49 +02:00
|
|
|
bgfx::submit(m_view_idx, shader_instance.m_program_handles[m_pass_idx]);
|
2015-10-06 17:00:52 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
data.buffer = nullptr;
|
|
|
|
data.instance_count = 0;
|
2016-01-22 18:02:07 +01:00
|
|
|
mesh.instance_idx = -1;
|
2015-08-27 23:18:49 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void applyCamera(const char* slot)
|
|
|
|
{
|
2016-01-12 19:37:00 +01:00
|
|
|
ComponentIndex cmp = m_scene->getCameraInSlot(slot);
|
2015-08-27 23:18:49 +02:00
|
|
|
if (cmp < 0) return;
|
|
|
|
|
2016-01-12 19:37:00 +01:00
|
|
|
m_scene->setCameraSize(cmp, m_width, m_height);
|
2015-08-27 23:18:49 +02:00
|
|
|
m_applied_camera = cmp;
|
2016-01-12 19:37:00 +01:00
|
|
|
m_camera_frustum = m_scene->getCameraFrustum(cmp);
|
2015-08-27 23:18:49 +02:00
|
|
|
|
|
|
|
Matrix projection_matrix;
|
2016-01-12 19:37:00 +01:00
|
|
|
float fov = m_scene->getCameraFOV(cmp);
|
|
|
|
float near_plane = m_scene->getCameraNearPlane(cmp);
|
|
|
|
float far_plane = m_scene->getCameraFarPlane(cmp);
|
2015-09-02 11:14:42 +02:00
|
|
|
float ratio = float(m_width) / m_height;
|
|
|
|
projection_matrix.setPerspective(
|
|
|
|
Math::degreesToRadians(fov), ratio, near_plane, far_plane);
|
2015-08-27 23:18:49 +02:00
|
|
|
|
2016-01-12 19:37:00 +01:00
|
|
|
Universe& universe = m_scene->getUniverse();
|
|
|
|
Matrix mtx = universe.getMatrix(m_scene->getCameraEntity(cmp));
|
2015-08-27 23:18:49 +02:00
|
|
|
mtx.fastInverse();
|
|
|
|
bgfx::setViewTransform(m_view_idx, &mtx.m11, &projection_matrix.m11);
|
2015-11-14 00:25:08 +01:00
|
|
|
|
2015-08-27 23:18:49 +02:00
|
|
|
bgfx::setViewRect(
|
2015-11-14 00:25:08 +01:00
|
|
|
m_view_idx, (uint16_t)m_view_x, (uint16_t)m_view_y, (uint16)m_width, (uint16)m_height);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void finishInstances()
|
|
|
|
{
|
|
|
|
for (int i = 0; i < lengthOf(m_instances_data); ++i)
|
|
|
|
{
|
|
|
|
finishInstances(i);
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
m_instance_data_idx = 0;
|
|
|
|
}
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2015-01-03 12:13:13 +01:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void setPass(const char* name)
|
|
|
|
{
|
|
|
|
m_pass_idx = m_renderer.getPassIdx(name);
|
2015-08-12 21:54:47 +02:00
|
|
|
for (int i = 0; i < m_view2pass_map.size(); ++i)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
if (m_view2pass_map[i] == m_pass_idx)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-11-14 00:25:08 +01:00
|
|
|
m_view_idx = (uint8)i;
|
2015-10-24 15:27:48 +02:00
|
|
|
return;
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
|
|
|
}
|
2015-07-31 22:22:37 +02:00
|
|
|
|
2016-01-18 21:28:17 +01:00
|
|
|
beginNewView(name);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
|
2015-07-05 15:58:53 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
CustomCommandHandler& addCustomCommandHandler(const char* name) override
|
|
|
|
{
|
2016-01-14 16:22:25 +01:00
|
|
|
auto& handler = m_custom_commands_handlers.emplace();
|
2016-01-12 19:37:00 +01:00
|
|
|
copyString(handler.name, name);
|
|
|
|
handler.hash = crc32(name);
|
|
|
|
exposeCustomCommandToLua(handler);
|
|
|
|
return handler;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-07-05 15:58:53 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
FrameBuffer* getFramebuffer(const char* framebuffer_name) override
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
for (int i = 0, c = m_framebuffers.size(); i < c; ++i)
|
2015-07-05 15:58:53 +02:00
|
|
|
{
|
2015-11-12 17:54:02 +01:00
|
|
|
if (compareString(m_framebuffers[i]->getName(), framebuffer_name) == 0)
|
2015-07-05 15:58:53 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
return m_framebuffers[i];
|
2015-07-05 15:58:53 +02:00
|
|
|
}
|
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
return nullptr;
|
|
|
|
}
|
2015-07-05 15:58:53 +02:00
|
|
|
|
2015-01-03 12:13:13 +01:00
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
void setFramebuffer(const char* framebuffer_name)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-11-12 17:54:02 +01:00
|
|
|
if (compareString(framebuffer_name, "default") == 0)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
m_current_framebuffer = m_default_framebuffer;
|
2015-07-12 18:29:23 +02:00
|
|
|
if (m_current_framebuffer)
|
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setViewFrameBuffer(m_view_idx,
|
|
|
|
m_current_framebuffer->getHandle());
|
2015-07-12 18:29:23 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bgfx::setViewFrameBuffer(m_view_idx, BGFX_INVALID_HANDLE);
|
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
return;
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
m_current_framebuffer = getFramebuffer(framebuffer_name);
|
|
|
|
if (m_current_framebuffer)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setViewFrameBuffer(m_view_idx,
|
|
|
|
m_current_framebuffer->getHandle());
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
g_log_warning.log("renderer") << "Framebuffer " << framebuffer_name
|
|
|
|
<< " not found";
|
|
|
|
}
|
|
|
|
}
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2014-07-13 16:54:09 +02:00
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
int getWidth() override { return m_width; }
|
2014-07-13 16:54:09 +02:00
|
|
|
|
2015-01-03 12:13:13 +01:00
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
int getHeight() override { return m_height; }
|
2015-07-23 23:17:51 +02:00
|
|
|
|
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
float getFPS()
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-01-15 00:05:53 +01:00
|
|
|
return m_renderer.getEngine().getFPS();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void executeCustomCommand(const char* name)
|
|
|
|
{
|
|
|
|
uint32 name_hash = crc32(name);
|
2015-07-23 23:17:51 +02:00
|
|
|
CustomCommandHandler handler;
|
2016-01-12 19:37:00 +01:00
|
|
|
for(auto& handler : m_custom_commands_handlers)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2016-01-15 00:05:53 +01:00
|
|
|
if(handler.hash == name_hash)
|
2016-01-12 19:37:00 +01:00
|
|
|
{
|
|
|
|
handler.callback.invoke();
|
|
|
|
break;
|
|
|
|
}
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2015-07-29 22:01:49 +02:00
|
|
|
finishInstances();
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-02-28 11:41:31 +01:00
|
|
|
|
|
|
|
|
2016-01-18 21:28:17 +01:00
|
|
|
void beginNewView(const char* debug_name)
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
2016-01-22 23:33:14 +01:00
|
|
|
m_bind_framebuffer_texture_idx = 0;
|
2015-09-02 11:14:42 +02:00
|
|
|
m_renderer.viewCounterAdd();
|
2015-11-14 00:25:08 +01:00
|
|
|
m_view_idx = (uint8)m_renderer.getViewCounter();
|
2015-09-02 11:14:42 +02:00
|
|
|
m_view2pass_map[m_view_idx] = m_pass_idx;
|
2016-01-18 21:28:17 +01:00
|
|
|
if (m_current_framebuffer)
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
2016-01-18 21:28:17 +01:00
|
|
|
bgfx::setViewFrameBuffer(m_view_idx, m_current_framebuffer->getHandle());
|
2015-09-04 14:00:28 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bgfx::setViewFrameBuffer(m_view_idx, BGFX_INVALID_HANDLE);
|
|
|
|
}
|
|
|
|
bgfx::setViewClear(m_view_idx, 0);
|
2015-11-04 22:43:54 +01:00
|
|
|
bgfx::setViewName(m_view_idx, debug_name);
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2016-01-24 17:20:03 +01:00
|
|
|
void copyRenderbuffer(const char* src_fb_name, int src_rb_idx, const char* dest_fb_name, int dest_rb_idx)
|
|
|
|
{
|
|
|
|
auto* src_fb = getFramebuffer(src_fb_name);
|
|
|
|
auto* dest_fb = getFramebuffer(dest_fb_name);
|
|
|
|
if (!src_fb || !dest_fb) return;
|
|
|
|
|
|
|
|
auto src_rb = src_fb->getRenderbufferHandle(src_rb_idx);
|
|
|
|
auto dest_rb = dest_fb->getRenderbufferHandle(dest_rb_idx);
|
|
|
|
|
|
|
|
bgfx::blit(m_view_idx, dest_rb, 0, 0, src_rb);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-26 10:27:31 +01:00
|
|
|
void createCubeBuffers()
|
|
|
|
{
|
|
|
|
const Vec3 cube_vertices[] = {
|
|
|
|
{-1, -1, -1}, {1, -1, -1}, {1, 1, -1}, {-1, 1, -1},
|
|
|
|
{-1, -1, 1}, {1, -1, 1}, {1, 1, 1}, {-1, 1, 1},
|
|
|
|
{1, -1, -1}, {1, -1, 1}, {1, 1, 1}, {1, 1, -1},
|
|
|
|
{-1, -1, -1}, {-1, -1, 1}, {-1, 1, 1}, {-1, 1, -1},
|
|
|
|
{-1, 1, -1}, {1, 1, -1}, {1, 1, 1}, {-1, 1, 1},
|
|
|
|
{-1, -1, -1}, {1, -1, -1}, {1, -1, 1}, {-1, -1, 1}
|
|
|
|
};
|
|
|
|
static const uint16 cube_indices[] = {
|
|
|
|
0, 2, 1, 2, 0, 3,
|
|
|
|
4, 5, 6, 6, 7, 4,
|
|
|
|
8, 10, 9, 10, 8, 11,
|
|
|
|
12, 13, 14, 14, 15, 12,
|
|
|
|
16, 18, 17, 18, 16, 19,
|
|
|
|
20, 21, 22, 22, 23, 20
|
|
|
|
};
|
|
|
|
auto* vertices_mem = bgfx::copy(cube_vertices, sizeof(cube_vertices));
|
|
|
|
auto* indices_mem = bgfx::copy(cube_indices, sizeof(cube_indices));
|
|
|
|
m_cube_vb = bgfx::createVertexBuffer(vertices_mem, m_deferred_point_light_vertex_decl);
|
|
|
|
m_cube_ib = bgfx::createIndexBuffer(indices_mem);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-26 16:49:47 +01:00
|
|
|
void finishDeferredPointLightInstances(Material* material,
|
2016-01-26 15:21:38 +01:00
|
|
|
TextureBindData* textures,
|
|
|
|
int textures_count,
|
|
|
|
const bgfx::InstanceDataBuffer* instance_buffer,
|
2016-01-28 15:19:56 +01:00
|
|
|
int instance_count,
|
2016-01-26 15:21:38 +01:00
|
|
|
bool is_intersecting)
|
|
|
|
{
|
2016-01-28 15:19:56 +01:00
|
|
|
bgfx::setInstanceDataBuffer(instance_buffer, instance_count);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
|
|
|
if (is_intersecting)
|
2016-01-26 15:21:38 +01:00
|
|
|
{
|
|
|
|
bgfx::setState((m_render_state | material->getRenderStates()) &
|
|
|
|
~BGFX_STATE_CULL_MASK & ~BGFX_STATE_DEPTH_TEST_MASK | BGFX_STATE_CULL_CCW);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
bgfx::setState(m_render_state | material->getRenderStates());
|
|
|
|
}
|
|
|
|
for(int i = 0; i < textures_count; ++i)
|
|
|
|
{
|
|
|
|
bgfx::setTexture(m_bind_framebuffer_texture_idx + i,
|
|
|
|
textures[i].uniform,
|
|
|
|
textures[i].texture);
|
|
|
|
}
|
|
|
|
bgfx::setVertexBuffer(m_cube_vb);
|
|
|
|
bgfx::setIndexBuffer(m_cube_ib);
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
m_stats.m_instance_count += instance_count;
|
|
|
|
m_stats.m_triangle_count += instance_count * 12;
|
|
|
|
bgfx::submit(m_view_idx, material->getShaderInstance().m_program_handles[m_pass_idx]);
|
2016-01-26 15:21:38 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-24 17:20:03 +01:00
|
|
|
void deferredLocalLightLoop(int material_index, TextureBindData* textures, int textures_count)
|
|
|
|
{
|
2016-01-26 01:18:05 +01:00
|
|
|
PROFILE_FUNCTION();
|
2016-01-24 17:20:03 +01:00
|
|
|
if (m_applied_camera == INVALID_COMPONENT) return;
|
2016-01-26 14:39:08 +01:00
|
|
|
auto* material = m_materials[material_index];
|
2016-01-26 16:49:47 +01:00
|
|
|
if (!material->isReady()) return;
|
2016-01-24 17:20:03 +01:00
|
|
|
|
|
|
|
m_tmp_local_lights.clear();
|
2016-01-26 15:21:38 +01:00
|
|
|
m_scene->getPointLights(m_camera_frustum, m_tmp_local_lights);
|
2016-01-24 17:20:03 +01:00
|
|
|
if (m_tmp_local_lights.empty()) return;
|
|
|
|
|
2016-01-26 14:39:08 +01:00
|
|
|
PROFILE_INT("light count", m_tmp_local_lights.size());
|
|
|
|
struct Data
|
2016-01-24 17:20:03 +01:00
|
|
|
{
|
2016-01-26 14:39:08 +01:00
|
|
|
Matrix mtx;
|
|
|
|
Vec4 pos_radius;
|
|
|
|
Vec4 color_attenuation;
|
|
|
|
Vec4 dir_fov;
|
|
|
|
Vec4 specular;
|
|
|
|
};
|
2016-01-26 15:21:38 +01:00
|
|
|
const bgfx::InstanceDataBuffer* instance_buffer[2] = {nullptr, nullptr};
|
|
|
|
Data* instance_data[2] = { nullptr, nullptr };
|
|
|
|
Universe& universe = m_scene->getUniverse();
|
2016-01-26 14:39:08 +01:00
|
|
|
for(auto light_cmp : m_tmp_local_lights)
|
|
|
|
{
|
|
|
|
auto entity = m_scene->getPointLightEntity(light_cmp);
|
|
|
|
float range = m_scene->getLightRange(light_cmp);
|
|
|
|
Vec3 light_dir = universe.getRotation(entity) * Vec3(0, 0, -1);
|
|
|
|
float attenuation = m_scene->getLightAttenuation(light_cmp);
|
|
|
|
float fov = Math::degreesToRadians(m_scene->getLightFOV(light_cmp));
|
2016-01-30 10:06:58 +01:00
|
|
|
float intensity = m_scene->getPointLightIntensity(light_cmp);
|
|
|
|
intensity *= intensity;
|
|
|
|
Vec3 color = m_scene->getPointLightColor(light_cmp) * intensity;
|
2016-01-26 14:39:08 +01:00
|
|
|
|
2016-01-26 15:21:38 +01:00
|
|
|
Vec3 pos = universe.getPosition(entity);
|
2016-01-28 19:35:00 +01:00
|
|
|
int buffer_idx = m_camera_frustum.intersectNearPlane(pos, range * Math::SQRT3) ? 0 : 1;
|
2016-01-26 15:21:38 +01:00
|
|
|
if(!instance_buffer[buffer_idx])
|
|
|
|
{
|
|
|
|
instance_buffer[buffer_idx] = bgfx::allocInstanceDataBuffer(128, sizeof(Data));
|
|
|
|
instance_data[buffer_idx] = (Data*)instance_buffer[buffer_idx]->data;
|
|
|
|
}
|
|
|
|
|
|
|
|
auto* id = instance_data[buffer_idx];
|
|
|
|
id->mtx = universe.getPositionAndRotation(entity);
|
|
|
|
id->mtx.multiply3x3(range);
|
|
|
|
id->pos_radius.set(pos, range);
|
|
|
|
id->color_attenuation.set(color, attenuation);
|
|
|
|
id->dir_fov.set(light_dir, fov);
|
2016-02-10 12:09:09 +01:00
|
|
|
float specular_intensity = m_scene->getPointLightSpecularIntensity(light_cmp);
|
|
|
|
id->specular.set(m_scene->getPointLightSpecularColor(light_cmp)
|
|
|
|
* specular_intensity * specular_intensity, 1);
|
2016-01-26 15:21:38 +01:00
|
|
|
++instance_data[buffer_idx];
|
|
|
|
|
|
|
|
if(instance_data[buffer_idx] - (Data*)instance_buffer[buffer_idx]->data == 128)
|
|
|
|
{
|
2016-01-26 16:49:47 +01:00
|
|
|
finishDeferredPointLightInstances(material,
|
2016-01-26 15:21:38 +01:00
|
|
|
textures,
|
|
|
|
textures_count,
|
|
|
|
instance_buffer[buffer_idx],
|
2016-01-28 15:19:56 +01:00
|
|
|
128,
|
2016-01-26 15:21:38 +01:00
|
|
|
buffer_idx == 0);
|
|
|
|
instance_buffer[buffer_idx] = nullptr;
|
|
|
|
instance_data[buffer_idx] = nullptr;
|
|
|
|
}
|
2016-01-24 17:20:03 +01:00
|
|
|
}
|
2016-01-26 15:21:38 +01:00
|
|
|
|
|
|
|
for(int buffer_idx = 0; buffer_idx < 2; ++buffer_idx)
|
2016-01-26 14:39:08 +01:00
|
|
|
{
|
2016-01-26 15:21:38 +01:00
|
|
|
if(instance_data[buffer_idx])
|
|
|
|
{
|
2016-01-26 16:49:47 +01:00
|
|
|
finishDeferredPointLightInstances(material,
|
2016-01-26 15:21:38 +01:00
|
|
|
textures,
|
|
|
|
textures_count,
|
|
|
|
instance_buffer[buffer_idx],
|
2016-01-28 21:44:35 +01:00
|
|
|
int(instance_data[buffer_idx] - (Data*)instance_buffer[buffer_idx]->data),
|
2016-01-26 15:21:38 +01:00
|
|
|
buffer_idx == 0);
|
|
|
|
}
|
2016-01-26 14:39:08 +01:00
|
|
|
}
|
2016-01-24 17:20:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-18 21:28:17 +01:00
|
|
|
void renderSpotLightShadowmap(ComponentIndex light, int64 layer_mask)
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
2016-01-18 21:28:17 +01:00
|
|
|
beginNewView("point_light");
|
2015-09-02 11:14:42 +02:00
|
|
|
|
|
|
|
Entity light_entity = m_scene->getPointLightEntity(light);
|
|
|
|
Matrix mtx = m_scene->getUniverse().getMatrix(light_entity);
|
|
|
|
float fov = m_scene->getLightFOV(light);
|
|
|
|
float range = m_scene->getLightRange(light);
|
2015-11-11 21:54:25 +01:00
|
|
|
uint16 shadowmap_height = (uint16)m_current_framebuffer->getHeight();
|
|
|
|
uint16 shadowmap_width = (uint16)m_current_framebuffer->getWidth();
|
2015-09-02 11:14:42 +02:00
|
|
|
Vec3 pos = mtx.getTranslation();
|
2016-01-26 14:39:08 +01:00
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
bgfx::setViewClear(m_view_idx, BGFX_CLEAR_DEPTH, 0, 1.0f, 0);
|
|
|
|
bgfx::touch(m_view_idx);
|
|
|
|
bgfx::setViewRect(m_view_idx, 0, 0, shadowmap_width, shadowmap_height);
|
|
|
|
|
|
|
|
Matrix projection_matrix;
|
2016-01-26 16:49:47 +01:00
|
|
|
projection_matrix.setPerspective(Math::degreesToRadians(fov), 1, 0.01f, range);
|
2015-09-02 11:14:42 +02:00
|
|
|
Matrix view_matrix;
|
2016-01-26 16:49:47 +01:00
|
|
|
view_matrix.lookAt(pos, pos - mtx.getZVector(), mtx.getYVector());
|
|
|
|
bgfx::setViewTransform(m_view_idx, &view_matrix.m11, &projection_matrix.m11);
|
2015-09-02 11:14:42 +02:00
|
|
|
|
2016-01-14 16:22:25 +01:00
|
|
|
PointLightShadowmap& s = m_point_light_shadowmaps.emplace();
|
2015-09-02 11:14:42 +02:00
|
|
|
s.m_framebuffer = m_current_framebuffer;
|
|
|
|
s.m_light = light;
|
|
|
|
static const Matrix biasMatrix(
|
|
|
|
0.5, 0.0, 0.0, 0.0,
|
|
|
|
0.0, -0.5, 0.0, 0.0,
|
|
|
|
0.0, 0.0, 0.5, 0.0,
|
|
|
|
0.5, 0.5, 0.5, 1.0);
|
2015-09-04 14:00:28 +02:00
|
|
|
s.m_matrices[0] = biasMatrix * (projection_matrix * view_matrix);
|
2015-09-02 11:14:42 +02:00
|
|
|
|
|
|
|
renderPointLightInfluencedGeometry(light, layer_mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-18 21:28:17 +01:00
|
|
|
void renderOmniLightShadowmap(ComponentIndex light, int64 layer_mask)
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
|
|
|
Entity light_entity = m_scene->getPointLightEntity(light);
|
|
|
|
Vec3 light_pos = m_scene->getUniverse().getPosition(light_entity);
|
|
|
|
float range = m_scene->getLightRange(light);
|
2016-01-18 21:28:17 +01:00
|
|
|
uint16 shadowmap_height = (uint16)m_current_framebuffer->getHeight();
|
|
|
|
uint16 shadowmap_width = (uint16)m_current_framebuffer->getWidth();
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
float viewports[] = {0, 0, 0.5, 0, 0, 0.5, 0.5, 0.5};
|
|
|
|
|
|
|
|
static const float YPR[4][3] = {
|
|
|
|
{Math::degreesToRadians(0.0f),
|
|
|
|
Math::degreesToRadians(27.36780516f),
|
|
|
|
Math::degreesToRadians(0.0f)},
|
|
|
|
{Math::degreesToRadians(180.0f),
|
|
|
|
Math::degreesToRadians(27.36780516f),
|
|
|
|
Math::degreesToRadians(0.0f)},
|
|
|
|
{Math::degreesToRadians(-90.0f),
|
|
|
|
Math::degreesToRadians(-27.36780516f),
|
|
|
|
Math::degreesToRadians(0.0f)},
|
|
|
|
{Math::degreesToRadians(90.0f),
|
|
|
|
Math::degreesToRadians(-27.36780516f),
|
|
|
|
Math::degreesToRadians(0.0f)},
|
|
|
|
};
|
|
|
|
|
2016-01-26 16:49:47 +01:00
|
|
|
PointLightShadowmap& shadowmap_info = m_point_light_shadowmaps.emplace();
|
2016-01-18 21:28:17 +01:00
|
|
|
shadowmap_info.m_framebuffer = m_current_framebuffer;
|
2015-09-04 14:00:28 +02:00
|
|
|
shadowmap_info.m_light = light;
|
|
|
|
|
|
|
|
for (int i = 0; i < 4; ++i)
|
|
|
|
{
|
2016-01-18 21:28:17 +01:00
|
|
|
beginNewView("omnilight");
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
bgfx::setViewClear(m_view_idx, BGFX_CLEAR_DEPTH, 0, 1.0f, 0);
|
|
|
|
bgfx::touch(m_view_idx);
|
2015-11-11 21:54:25 +01:00
|
|
|
uint16 view_x = uint16(shadowmap_width * viewports[i * 2]);
|
|
|
|
uint16 view_y = uint16(shadowmap_height * viewports[i * 2 + 1]);
|
2016-01-26 16:49:47 +01:00
|
|
|
bgfx::setViewRect(
|
|
|
|
m_view_idx, view_x, view_y, shadowmap_width >> 1, shadowmap_height >> 1);
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
float fovx = Math::degreesToRadians(143.98570868f + 3.51f);
|
|
|
|
float fovy = Math::degreesToRadians(125.26438968f + 9.85f);
|
|
|
|
float aspect = tanf(fovx * 0.5f) / tanf(fovy * 0.5f);
|
|
|
|
|
|
|
|
Matrix projection_matrix;
|
|
|
|
projection_matrix.setPerspective(fovx, aspect, 0.01f, range);
|
2016-01-26 14:39:08 +01:00
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
Matrix view_matrix;
|
|
|
|
view_matrix.fromEuler(YPR[i][0], YPR[i][1], YPR[i][2]);
|
|
|
|
view_matrix.setTranslation(light_pos);
|
|
|
|
Frustum frustum;
|
|
|
|
frustum.computePerspective(light_pos,
|
|
|
|
view_matrix.getZVector(),
|
|
|
|
view_matrix.getYVector(),
|
|
|
|
fovx,
|
|
|
|
aspect,
|
|
|
|
0.01f,
|
|
|
|
range);
|
2016-01-26 14:39:08 +01:00
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
view_matrix.fastInverse();
|
|
|
|
|
2016-01-26 16:49:47 +01:00
|
|
|
bgfx::setViewTransform(m_view_idx, &view_matrix.m11, &projection_matrix.m11);
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
static const Matrix biasMatrix(
|
2016-01-26 16:49:47 +01:00
|
|
|
0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.5, 1.0);
|
2015-09-04 14:00:28 +02:00
|
|
|
shadowmap_info.m_matrices[i] = biasMatrix * (projection_matrix * view_matrix);
|
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
renderLitModels(light, frustum, layer_mask);
|
2015-09-04 14:00:28 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
void renderLitModels(ComponentIndex light, const Frustum& frustum, int64 layer_mask)
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
|
|
|
|
m_tmp_meshes.clear();
|
|
|
|
m_current_light = light;
|
|
|
|
m_is_current_light_global = false;
|
2016-01-15 00:05:53 +01:00
|
|
|
m_scene->getPointLightInfluencedGeometry(light, frustum, m_tmp_meshes, layer_mask);
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
renderMeshes(m_tmp_meshes);
|
|
|
|
m_current_light = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
void renderLocalLightShadowmaps(ComponentIndex camera,
|
2016-01-26 16:49:47 +01:00
|
|
|
FrameBuffer** fbs,
|
|
|
|
int framebuffers_count,
|
|
|
|
int64 layer_mask)
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
2015-11-17 02:52:40 +01:00
|
|
|
if (camera < 0) return;
|
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
Universe& universe = m_scene->getUniverse();
|
|
|
|
Entity camera_entity = m_scene->getCameraEntity(camera);
|
|
|
|
Vec3 camera_pos = universe.getPosition(camera_entity);
|
|
|
|
|
|
|
|
ComponentIndex lights[16];
|
2016-01-18 21:28:17 +01:00
|
|
|
int light_count = m_scene->getClosestPointLights(camera_pos, lights, lengthOf(lights));
|
2015-09-02 11:14:42 +02:00
|
|
|
|
|
|
|
int fb_index = 0;
|
|
|
|
for (int i = 0; i < light_count; ++i)
|
|
|
|
{
|
|
|
|
if (!m_scene->getLightCastShadows(lights[i])) continue;
|
|
|
|
if (fb_index == framebuffers_count) break;
|
|
|
|
|
|
|
|
float fov = m_scene->getLightFOV(lights[i]);
|
2016-01-26 16:49:47 +01:00
|
|
|
|
2016-01-18 21:28:17 +01:00
|
|
|
m_current_framebuffer = fbs[i];
|
|
|
|
bgfx::setViewFrameBuffer(m_view_idx, m_current_framebuffer->getHandle());
|
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
if (fov < 180)
|
|
|
|
{
|
2016-01-18 21:28:17 +01:00
|
|
|
renderSpotLightShadowmap(lights[i], layer_mask);
|
2015-09-02 11:14:42 +02:00
|
|
|
++fb_index;
|
|
|
|
continue;
|
|
|
|
}
|
2015-09-04 14:00:28 +02:00
|
|
|
else
|
|
|
|
{
|
2016-01-18 21:28:17 +01:00
|
|
|
renderOmniLightShadowmap(lights[i], layer_mask);
|
2015-09-04 14:00:28 +02:00
|
|
|
++fb_index;
|
|
|
|
continue;
|
|
|
|
}
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-18 17:42:27 +02:00
|
|
|
static Vec3 shadowmapTexelAlign(const Vec3& shadow_cam_pos,
|
|
|
|
float shadowmap_width,
|
|
|
|
float frustum_radius,
|
|
|
|
const Matrix& light_mtx)
|
|
|
|
{
|
|
|
|
Matrix inv = light_mtx;
|
|
|
|
inv.fastInverse();
|
|
|
|
Vec3 out = inv.multiplyPosition(shadow_cam_pos);
|
|
|
|
float align = 2 * frustum_radius / (shadowmap_width * 0.5f - 2);
|
|
|
|
out.x -= fmodf(out.x, align);
|
|
|
|
out.y -= fmodf(out.y, align);
|
|
|
|
out = light_mtx.multiplyPosition(out);
|
|
|
|
return out;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-26 16:49:47 +01:00
|
|
|
void renderShadowmap(int64 layer_mask)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
Universe& universe = m_scene->getUniverse();
|
2015-07-24 08:42:35 +02:00
|
|
|
ComponentIndex light_cmp = m_scene->getActiveGlobalLight();
|
2016-01-26 16:49:47 +01:00
|
|
|
if (light_cmp < 0 || m_applied_camera < 0) return;
|
|
|
|
float camera_height = m_scene->getCameraHeight(m_applied_camera);
|
2015-11-11 23:25:44 +01:00
|
|
|
if (!camera_height) return;
|
2015-02-28 11:41:31 +01:00
|
|
|
|
2015-09-27 23:13:40 +02:00
|
|
|
Matrix light_mtx = universe.getMatrix(m_scene->getGlobalLightEntity(light_cmp));
|
2015-10-05 22:44:03 +02:00
|
|
|
m_global_light_shadowmap = m_current_framebuffer;
|
2015-07-23 23:17:51 +02:00
|
|
|
float shadowmap_height = (float)m_current_framebuffer->getHeight();
|
|
|
|
float shadowmap_width = (float)m_current_framebuffer->getWidth();
|
2016-01-26 23:33:28 +01:00
|
|
|
float viewports[] = { 0, 0, 0.5f, 0, 0, 0.5f, 0.5f, 0.5f };
|
2016-01-26 16:49:47 +01:00
|
|
|
float camera_fov = Math::degreesToRadians(m_scene->getCameraFOV(m_applied_camera));
|
|
|
|
float camera_ratio = m_scene->getCameraWidth(m_applied_camera) / camera_height;
|
2015-09-10 22:14:54 +02:00
|
|
|
Vec4 cascades = m_scene->getShadowmapCascades(light_cmp);
|
2016-01-26 23:33:28 +01:00
|
|
|
float split_distances[] = { 0.01f, cascades.x, cascades.y, cascades.z, cascades.w };
|
2015-10-06 00:30:12 +02:00
|
|
|
m_is_rendering_in_shadowmap = true;
|
2015-07-23 23:17:51 +02:00
|
|
|
for (int split_index = 0; split_index < 4; ++split_index)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2016-01-18 21:28:17 +01:00
|
|
|
if (split_index > 0) beginNewView("shadowmap");
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-09-27 23:13:40 +02:00
|
|
|
bgfx::setViewClear(
|
|
|
|
m_view_idx, BGFX_CLEAR_DEPTH | BGFX_CLEAR_COLOR, 0xffffffff, 1.0f, 0);
|
2015-08-04 22:34:27 +02:00
|
|
|
bgfx::touch(m_view_idx);
|
2015-07-23 23:17:51 +02:00
|
|
|
float* viewport = viewports + split_index * 2;
|
|
|
|
bgfx::setViewRect(m_view_idx,
|
2015-11-11 21:54:25 +01:00
|
|
|
(uint16)(1 + shadowmap_width * viewport[0]),
|
|
|
|
(uint16)(1 + shadowmap_height * viewport[1]),
|
|
|
|
(uint16)(0.5f * shadowmap_width - 2),
|
|
|
|
(uint16)(0.5f * shadowmap_height - 2));
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2016-01-26 23:33:28 +01:00
|
|
|
Frustum frustum;
|
2016-01-26 16:49:47 +01:00
|
|
|
Matrix camera_matrix = universe.getMatrix(m_scene->getCameraEntity(m_applied_camera));
|
2016-01-26 23:33:28 +01:00
|
|
|
frustum.computePerspective(camera_matrix.getTranslation(),
|
|
|
|
camera_matrix.getZVector(),
|
|
|
|
camera_matrix.getYVector(),
|
|
|
|
camera_fov,
|
|
|
|
camera_ratio,
|
|
|
|
split_distances[split_index],
|
|
|
|
split_distances[split_index + 1]);
|
|
|
|
|
2015-09-07 13:32:19 +02:00
|
|
|
Vec3 shadow_cam_pos = camera_matrix.getTranslation();
|
2016-01-26 23:33:28 +01:00
|
|
|
float bb_size = frustum.getRadius();
|
2015-10-18 17:42:27 +02:00
|
|
|
shadow_cam_pos =
|
|
|
|
shadowmapTexelAlign(shadow_cam_pos, 0.5f * shadowmap_width - 2, bb_size, light_mtx);
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
Matrix projection_matrix;
|
2015-09-27 23:13:40 +02:00
|
|
|
projection_matrix.setOrtho(
|
|
|
|
bb_size, -bb_size, -bb_size, bb_size, SHADOW_CAM_NEAR, SHADOW_CAM_FAR);
|
2015-07-23 23:17:51 +02:00
|
|
|
Vec3 light_forward = light_mtx.getZVector();
|
|
|
|
shadow_cam_pos -= light_forward * SHADOW_CAM_FAR * 0.5f;
|
|
|
|
Matrix view_matrix;
|
2015-09-27 23:13:40 +02:00
|
|
|
view_matrix.lookAt(
|
|
|
|
shadow_cam_pos, shadow_cam_pos + light_forward, light_mtx.getYVector());
|
|
|
|
bgfx::setViewTransform(m_view_idx, &view_matrix.m11, &projection_matrix.m11);
|
|
|
|
static const Matrix biasMatrix(
|
|
|
|
0.5, 0.0, 0.0, 0.0, 0.0, -0.5, 0.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.5, 1.0);
|
|
|
|
m_shadow_viewprojection[split_index] = biasMatrix * (projection_matrix * view_matrix);
|
2015-07-23 23:17:51 +02:00
|
|
|
|
|
|
|
Frustum shadow_camera_frustum;
|
|
|
|
shadow_camera_frustum.computeOrtho(shadow_cam_pos,
|
2015-09-27 23:13:40 +02:00
|
|
|
-light_forward,
|
|
|
|
light_mtx.getYVector(),
|
|
|
|
bb_size * 2,
|
|
|
|
bb_size * 2,
|
|
|
|
SHADOW_CAM_NEAR,
|
|
|
|
SHADOW_CAM_FAR);
|
|
|
|
renderAll(shadow_camera_frustum, layer_mask, false);
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
2015-10-06 00:30:12 +02:00
|
|
|
m_is_rendering_in_shadowmap = false;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-05-20 23:35:09 +02:00
|
|
|
|
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
void renderDebugShapes()
|
|
|
|
{
|
|
|
|
renderDebugLines();
|
|
|
|
renderDebugPoints();
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-08-28 21:55:53 +02:00
|
|
|
void renderDebugPoints()
|
|
|
|
{
|
|
|
|
const Array<DebugPoint>& points = m_scene->getDebugPoints();
|
|
|
|
if (points.empty() || !m_debug_line_material->isReady())
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
bgfx::TransientVertexBuffer tvb;
|
|
|
|
bgfx::TransientIndexBuffer tib;
|
2015-10-24 15:27:48 +02:00
|
|
|
if (bgfx::allocTransientBuffers(
|
|
|
|
&tvb, m_base_vertex_decl, points.size(), &tib, points.size()))
|
2015-08-28 21:55:53 +02:00
|
|
|
{
|
|
|
|
BaseVertex* vertex = (BaseVertex*)tvb.data;
|
2015-11-11 21:54:25 +01:00
|
|
|
uint16* indices = (uint16*)tib.data;
|
2015-08-28 21:55:53 +02:00
|
|
|
for (int i = 0; i < points.size(); ++i)
|
|
|
|
{
|
|
|
|
const DebugPoint& point = points[i];
|
2016-01-24 17:20:03 +01:00
|
|
|
vertex[0].rgba = point.m_color;
|
|
|
|
vertex[0].x = point.m_pos.x;
|
|
|
|
vertex[0].y = point.m_pos.y;
|
|
|
|
vertex[0].z = point.m_pos.z;
|
|
|
|
vertex[0].u = vertex[0].v = 0;
|
2015-08-28 21:55:53 +02:00
|
|
|
|
|
|
|
indices[0] = i;
|
|
|
|
++vertex;
|
|
|
|
++indices;
|
|
|
|
}
|
|
|
|
|
|
|
|
bgfx::setVertexBuffer(&tvb);
|
|
|
|
bgfx::setIndexBuffer(&tib);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2015-10-24 15:27:48 +02:00
|
|
|
bgfx::setState(
|
|
|
|
m_render_state | m_debug_line_material->getRenderStates() | BGFX_STATE_PT_POINTS);
|
2015-08-28 21:55:53 +02:00
|
|
|
bgfx::submit(m_view_idx,
|
2015-10-24 15:27:48 +02:00
|
|
|
m_debug_line_material->getShaderInstance().m_program_handles[m_pass_idx]);
|
2015-08-28 21:55:53 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void renderDebugLines()
|
|
|
|
{
|
|
|
|
const Array<DebugLine>& lines = m_scene->getDebugLines();
|
2015-10-24 12:25:06 +02:00
|
|
|
if (lines.empty() || !m_debug_line_material->isReady()) return;
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::TransientVertexBuffer tvb;
|
|
|
|
bgfx::TransientIndexBuffer tib;
|
2015-10-24 15:27:48 +02:00
|
|
|
if (bgfx::allocTransientBuffers(
|
|
|
|
&tvb, m_base_vertex_decl, lines.size() * 2, &tib, lines.size() * 2))
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
BaseVertex* vertex = (BaseVertex*)tvb.data;
|
2015-11-11 21:54:25 +01:00
|
|
|
uint16* indices = (uint16*)tib.data;
|
2015-07-23 23:17:51 +02:00
|
|
|
for (int i = 0; i < lines.size(); ++i)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
const DebugLine& line = lines[i];
|
2016-01-24 17:20:03 +01:00
|
|
|
vertex[0].rgba = line.m_color;
|
|
|
|
vertex[0].x = line.m_from.x;
|
|
|
|
vertex[0].y = line.m_from.y;
|
|
|
|
vertex[0].z = line.m_from.z;
|
|
|
|
vertex[0].u = vertex[0].v = 0;
|
|
|
|
|
|
|
|
vertex[1].rgba = line.m_color;
|
|
|
|
vertex[1].x = line.m_to.x;
|
|
|
|
vertex[1].y = line.m_to.y;
|
|
|
|
vertex[1].z = line.m_to.z;
|
|
|
|
vertex[1].u = vertex[0].v = 0;
|
2015-07-23 23:17:51 +02:00
|
|
|
|
|
|
|
indices[0] = i * 2;
|
|
|
|
indices[1] = i * 2 + 1;
|
|
|
|
vertex += 2;
|
|
|
|
indices += 2;
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
|
|
|
|
bgfx::setVertexBuffer(&tvb);
|
|
|
|
bgfx::setIndexBuffer(&tib);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2015-10-24 12:25:06 +02:00
|
|
|
bgfx::setState(
|
|
|
|
m_render_state | m_debug_line_material->getRenderStates() | BGFX_STATE_PT_LINES);
|
2015-08-04 22:34:27 +02:00
|
|
|
bgfx::submit(m_view_idx,
|
2015-10-24 12:25:06 +02:00
|
|
|
m_debug_line_material->getShaderInstance().m_program_handles[m_pass_idx]);
|
2014-06-03 16:43:35 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-06-03 16:43:35 +02:00
|
|
|
|
2014-09-26 23:50:05 +02:00
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
int getPassIdx() const override
|
2015-10-15 20:53:13 +02:00
|
|
|
{
|
|
|
|
return m_pass_idx;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
void setPointLightUniforms(Material* material, ComponentIndex light_cmp)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-10-05 22:44:03 +02:00
|
|
|
if (light_cmp < 0) return;
|
2015-07-24 08:42:35 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
Universe& universe = m_scene->getUniverse();
|
2015-09-05 13:08:47 +02:00
|
|
|
Entity light_entity = m_scene->getPointLightEntity(light_cmp);
|
|
|
|
Vec3 light_pos = universe.getPosition(light_entity);
|
2016-01-24 23:40:20 +01:00
|
|
|
Vec3 light_dir = universe.getRotation(light_entity) * Vec3(0, 0, -1);
|
2015-09-05 13:08:47 +02:00
|
|
|
float fov = Math::degreesToRadians(m_scene->getLightFOV(light_cmp));
|
2016-01-30 10:06:58 +01:00
|
|
|
float intensity = m_scene->getPointLightIntensity(light_cmp);
|
|
|
|
intensity *= intensity;
|
|
|
|
Vec3 color = m_scene->getPointLightColor(light_cmp) * intensity;
|
2015-10-06 17:00:52 +02:00
|
|
|
float range = m_scene->getLightRange(light_cmp);
|
|
|
|
float attenuation = m_scene->getLightAttenuation(light_cmp);
|
|
|
|
Vec4 light_pos_radius(light_pos, range);
|
2016-01-26 13:21:56 +01:00
|
|
|
Vec4 light_color_attenuation(color, attenuation);
|
2015-09-05 13:08:47 +02:00
|
|
|
Vec4 light_dir_fov(light_dir, fov);
|
2016-02-10 12:09:09 +01:00
|
|
|
float specular_intensity = m_scene->getPointLightSpecularIntensity(light_cmp);
|
|
|
|
Vec4 light_specular(m_scene->getPointLightSpecularColor(light_cmp) * specular_intensity *
|
|
|
|
specular_intensity, 1);
|
2015-09-04 14:00:28 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setUniform(m_light_pos_radius_uniform, &light_pos_radius);
|
2016-01-26 13:21:56 +01:00
|
|
|
bgfx::setUniform(m_light_color_attenuation_uniform, &light_color_attenuation);
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setUniform(m_light_dir_fov_uniform, &light_dir_fov);
|
|
|
|
bgfx::setUniform(m_light_specular_uniform, &light_specular);
|
2015-07-24 08:42:35 +02:00
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
if (m_scene->getLightCastShadows(light_cmp))
|
|
|
|
{
|
2015-09-05 13:08:47 +02:00
|
|
|
setPointLightShadowmapUniforms(material, light_cmp);
|
2015-09-04 14:00:28 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2016-02-08 00:18:19 +01:00
|
|
|
material->setDefine(m_has_shadowmap_define_idx, false);
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2016-02-10 00:00:21 +01:00
|
|
|
void clearStencil()
|
|
|
|
{
|
|
|
|
m_stencil = BGFX_STENCIL_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setStencilRef(uint32 ref)
|
|
|
|
{
|
|
|
|
m_stencil |= BGFX_STENCIL_FUNC_REF(ref);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setStencilRMask(uint32 rmask)
|
|
|
|
{
|
|
|
|
m_stencil |= BGFX_STENCIL_FUNC_RMASK(rmask);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void setStencil(uint32 flags)
|
|
|
|
{
|
|
|
|
m_stencil |= flags;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-08 23:23:07 +01:00
|
|
|
void setActiveDirectionalLightUniforms()
|
|
|
|
{
|
|
|
|
setDirectionalLightUniforms(m_scene->getActiveGlobalLight());
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
void setPointLightShadowmapUniforms(Material* material, ComponentIndex light)
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
|
|
|
for (auto& info : m_point_light_shadowmaps)
|
|
|
|
{
|
|
|
|
if (info.m_light == light)
|
|
|
|
{
|
2016-02-08 00:18:19 +01:00
|
|
|
material->setDefine(m_has_shadowmap_define_idx, true);
|
2015-09-04 14:00:28 +02:00
|
|
|
|
|
|
|
bgfx::setUniform(m_shadowmap_matrices_uniform,
|
2015-10-24 15:27:48 +02:00
|
|
|
&info.m_matrices[0].m11,
|
|
|
|
m_scene->getLightFOV(light) > 180 ? 4 : 1);
|
2015-09-04 14:00:28 +02:00
|
|
|
|
2015-10-31 01:05:20 +01:00
|
|
|
int texture_offset = material->getShader()->getTextureSlotCount();
|
2015-10-05 22:44:03 +02:00
|
|
|
bgfx::setTexture(texture_offset,
|
|
|
|
m_tex_shadowmap_uniform,
|
|
|
|
info.m_framebuffer->getRenderbufferHandle(0));
|
2015-09-04 14:00:28 +02:00
|
|
|
return;
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
}
|
2016-02-08 00:18:19 +01:00
|
|
|
material->setDefine(m_has_shadowmap_define_idx, false);
|
2015-09-02 11:14:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
void setDirectionalLightUniforms(ComponentIndex light_cmp) const
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-10-17 00:18:47 +02:00
|
|
|
if (light_cmp < 0) return;
|
2015-07-24 08:42:35 +02:00
|
|
|
|
2016-01-26 13:21:56 +01:00
|
|
|
bgfx::setUniform(m_light_color_attenuation_uniform, &m_directional_light_uniforms.diffuse_light_color);
|
2016-01-22 18:12:59 +01:00
|
|
|
bgfx::setUniform(m_ambient_color_uniform, &m_directional_light_uniforms.ambient_light_color);
|
|
|
|
bgfx::setUniform(m_light_dir_fov_uniform, &m_directional_light_uniforms.light_dir_fov);
|
|
|
|
bgfx::setUniform(m_fog_color_density_uniform, &m_directional_light_uniforms.fog_color_density);
|
|
|
|
bgfx::setUniform(m_fog_params_uniform, &m_directional_light_uniforms.fog_params);
|
2015-10-17 00:18:47 +02:00
|
|
|
bgfx::setUniform(m_shadowmap_matrices_uniform, &m_shadow_viewprojection, 4);
|
2016-01-28 21:44:35 +01:00
|
|
|
bgfx::setUniform(m_light_specular_uniform, &m_directional_light_uniforms.specular);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
void disableBlending() { m_render_state &= ~BGFX_STATE_BLEND_MASK; }
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
void enableDepthWrite() { m_render_state |= BGFX_STATE_DEPTH_WRITE; }
|
|
|
|
void disableDepthWrite() { m_render_state &= ~BGFX_STATE_DEPTH_WRITE; }
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
void enableAlphaWrite() { m_render_state |= BGFX_STATE_ALPHA_WRITE; }
|
|
|
|
void disableAlphaWrite() { m_render_state &= ~BGFX_STATE_ALPHA_WRITE; }
|
2015-07-10 08:12:12 +02:00
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
void enableRGBWrite() { m_render_state |= BGFX_STATE_RGB_WRITE; }
|
|
|
|
void disableRGBWrite() { m_render_state &= ~BGFX_STATE_RGB_WRITE; }
|
2014-11-30 15:10:13 +01:00
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
void renderPointLightInfluencedGeometry(ComponentIndex light, int64 layer_mask)
|
2015-09-02 11:14:42 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
|
|
|
|
m_tmp_meshes.clear();
|
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
m_scene->getPointLightInfluencedGeometry(light, m_tmp_meshes, layer_mask);
|
2015-09-02 11:14:42 +02:00
|
|
|
|
|
|
|
renderMeshes(m_tmp_meshes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-26 16:49:47 +01:00
|
|
|
void renderPointLightInfluencedGeometry(const Frustum& frustum, int64 layer_mask)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2014-11-30 15:10:13 +01:00
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
Array<ComponentIndex> lights(m_allocator);
|
2015-07-23 23:17:51 +02:00
|
|
|
m_scene->getPointLights(frustum, lights);
|
|
|
|
for (int i = 0; i < lights.size(); ++i)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
m_tmp_grasses.clear();
|
|
|
|
m_tmp_meshes.clear();
|
|
|
|
m_tmp_terrains.clear();
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2015-07-24 08:42:35 +02:00
|
|
|
ComponentIndex light = lights[i];
|
2015-09-02 11:14:42 +02:00
|
|
|
m_current_light = light;
|
|
|
|
m_is_current_light_global = false;
|
2015-10-24 15:27:48 +02:00
|
|
|
m_scene->getPointLightInfluencedGeometry(light, frustum, m_tmp_meshes, layer_mask);
|
2014-05-21 20:16:57 +02:00
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
m_scene->getTerrainInfos(m_tmp_terrains,
|
2015-07-23 23:17:51 +02:00
|
|
|
layer_mask,
|
2015-10-24 15:27:48 +02:00
|
|
|
m_scene->getUniverse().getPosition(m_scene->getCameraEntity(m_applied_camera)),
|
2015-09-26 19:59:14 +02:00
|
|
|
m_renderer.getFrameAllocator());
|
2014-09-29 01:53:17 +02:00
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
m_scene->getGrassInfos(frustum, m_tmp_grasses, layer_mask, m_applied_camera);
|
2015-07-23 23:17:51 +02:00
|
|
|
renderMeshes(m_tmp_meshes);
|
|
|
|
renderTerrains(m_tmp_terrains);
|
|
|
|
renderGrasses(m_tmp_grasses);
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2015-09-03 14:25:12 +02:00
|
|
|
m_current_light = -1;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2014-09-29 01:53:17 +02:00
|
|
|
|
2015-09-11 03:58:02 +02:00
|
|
|
void drawQuad(float x, float y, float w, float h, int material_index)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-09-11 03:58:02 +02:00
|
|
|
Material* material = m_materials[material_index];
|
2015-10-24 15:27:48 +02:00
|
|
|
if (!material->isReady() || !bgfx::checkAvailTransientVertexBuffer(3, m_base_vertex_decl))
|
|
|
|
{
|
2015-10-29 00:09:01 +01:00
|
|
|
bgfx::touch(m_view_idx);
|
2015-08-27 23:18:49 +02:00
|
|
|
return;
|
2015-10-24 15:27:48 +02:00
|
|
|
}
|
2015-08-11 22:55:17 +02:00
|
|
|
|
2015-08-27 23:18:49 +02:00
|
|
|
Matrix projection_mtx;
|
|
|
|
projection_mtx.setOrtho(-1, 1, 1, -1, 0, 30);
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
bgfx::setViewTransform(m_view_idx, &Matrix::IDENTITY.m11, &projection_mtx.m11);
|
2015-10-26 21:26:10 +01:00
|
|
|
if (m_current_framebuffer)
|
|
|
|
{
|
|
|
|
bgfx::setViewRect(m_view_idx,
|
|
|
|
m_view_x,
|
|
|
|
m_view_y,
|
2015-11-11 21:54:25 +01:00
|
|
|
(uint16)m_current_framebuffer->getWidth(),
|
|
|
|
(uint16)m_current_framebuffer->getHeight());
|
2015-10-26 21:26:10 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-11-11 21:54:25 +01:00
|
|
|
bgfx::setViewRect(m_view_idx, m_view_x, m_view_y, (uint16)m_width, (uint16)m_height);
|
2015-10-26 21:26:10 +01:00
|
|
|
}
|
2015-08-27 23:18:49 +02:00
|
|
|
|
|
|
|
bgfx::TransientVertexBuffer vb;
|
2015-10-24 15:27:48 +02:00
|
|
|
bgfx::allocTransientVertexBuffer(&vb, 6, m_base_vertex_decl);
|
2015-08-27 23:18:49 +02:00
|
|
|
BaseVertex* vertex = (BaseVertex*)vb.data;
|
|
|
|
float x2 = x + w;
|
|
|
|
float y2 = y + h;
|
|
|
|
|
2016-01-24 17:20:03 +01:00
|
|
|
vertex[0].x = x;
|
|
|
|
vertex[0].y = y;
|
|
|
|
vertex[0].z = 0;
|
|
|
|
vertex[0].rgba = 0xffffffff;
|
|
|
|
vertex[0].u = 0;
|
|
|
|
vertex[0].v = 0;
|
|
|
|
|
|
|
|
vertex[1].x = x2;
|
|
|
|
vertex[1].y = y;
|
|
|
|
vertex[1].z = 0;
|
|
|
|
vertex[1].rgba = 0xffffffff;
|
|
|
|
vertex[1].u = 1;
|
|
|
|
vertex[1].v = 0;
|
|
|
|
|
|
|
|
vertex[2].x = x2;
|
|
|
|
vertex[2].y = y2;
|
|
|
|
vertex[2].z = 0;
|
|
|
|
vertex[2].rgba = 0xffffffff;
|
|
|
|
vertex[2].u = 1;
|
|
|
|
vertex[2].v = 1;
|
|
|
|
|
|
|
|
vertex[3].x = x;
|
|
|
|
vertex[3].y = y;
|
|
|
|
vertex[3].z = 0;
|
|
|
|
vertex[3].rgba = 0xffffffff;
|
|
|
|
vertex[3].u = 0;
|
|
|
|
vertex[3].v = 0;
|
|
|
|
|
|
|
|
vertex[4].x = x2;
|
|
|
|
vertex[4].y = y2;
|
|
|
|
vertex[4].z = 0;
|
|
|
|
vertex[4].rgba = 0xffffffff;
|
|
|
|
vertex[4].u = 1;
|
|
|
|
vertex[4].v = 1;
|
|
|
|
|
|
|
|
vertex[5].x = x;
|
|
|
|
vertex[5].y = y2;
|
|
|
|
vertex[5].z = 0;
|
|
|
|
vertex[5].rgba = 0xffffffff;
|
|
|
|
vertex[5].u = 0;
|
|
|
|
vertex[5].v = 1;
|
2015-08-27 23:18:49 +02:00
|
|
|
|
2016-02-09 19:21:00 +01:00
|
|
|
Shader* shader = material->getShader();
|
|
|
|
for (int i = 0; i < shader->getUniformCount(); ++i)
|
2015-09-25 02:46:36 +02:00
|
|
|
{
|
|
|
|
const Material::Uniform& uniform = material->getUniform(i);
|
2016-02-09 19:21:00 +01:00
|
|
|
const Shader::Uniform& shader_uniform = shader->getUniform(i);
|
2015-09-25 02:46:36 +02:00
|
|
|
|
2016-02-09 19:21:00 +01:00
|
|
|
switch (shader_uniform.type)
|
2015-09-25 02:46:36 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::FLOAT:
|
2015-10-24 15:27:48 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
Vec4 v(uniform.float_value, 0, 0, 0);
|
|
|
|
bgfx::setUniform(shader_uniform.handle, &v);
|
2015-10-24 15:27:48 +02:00
|
|
|
}
|
|
|
|
break;
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::COLOR:
|
|
|
|
case Shader::Uniform::VEC3:
|
2016-02-08 23:23:07 +01:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
Vec4 v(*(Vec3*)uniform.vec3, 0);
|
|
|
|
bgfx::setUniform(shader_uniform.handle, &v);
|
2016-02-08 23:23:07 +01:00
|
|
|
}
|
|
|
|
break;
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::TIME:
|
2015-10-24 15:27:48 +02:00
|
|
|
{
|
|
|
|
Vec4 v(m_scene->getTime(), 0, 0, 0);
|
2016-02-09 19:21:00 +01:00
|
|
|
bgfx::setUniform(shader_uniform.handle, &v);
|
2015-10-24 15:27:48 +02:00
|
|
|
}
|
2015-09-25 02:46:36 +02:00
|
|
|
break;
|
2015-10-24 15:27:48 +02:00
|
|
|
default: ASSERT(false); break;
|
2015-09-25 02:46:36 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 0; i < material->getTextureCount(); ++i)
|
|
|
|
{
|
|
|
|
Texture* texture = material->getTexture(i);
|
|
|
|
if (texture)
|
|
|
|
{
|
|
|
|
bgfx::setTexture(
|
2015-10-24 15:27:48 +02:00
|
|
|
i, shader->getTextureSlot(i).m_uniform_handle, texture->getTextureHandle());
|
2015-09-25 02:46:36 +02:00
|
|
|
}
|
2015-10-05 22:44:03 +02:00
|
|
|
}
|
2015-08-27 23:18:49 +02:00
|
|
|
|
2016-01-28 21:44:35 +01:00
|
|
|
if (m_is_current_light_global)
|
|
|
|
{
|
|
|
|
setDirectionalLightUniforms(m_current_light);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
setPointLightUniforms(material, m_current_light);
|
|
|
|
}
|
|
|
|
|
2015-09-11 03:58:02 +02:00
|
|
|
if (m_applied_camera >= 0)
|
|
|
|
{
|
|
|
|
Matrix projection_matrix;
|
2016-01-24 17:20:03 +01:00
|
|
|
Universe& universe = m_scene->getUniverse();
|
2016-01-12 19:37:00 +01:00
|
|
|
float fov = m_scene->getCameraFOV(m_applied_camera);
|
|
|
|
float near_plane = m_scene->getCameraNearPlane(m_applied_camera);
|
|
|
|
float far_plane = m_scene->getCameraFarPlane(m_applied_camera);
|
2015-09-11 03:58:02 +02:00
|
|
|
float ratio = float(m_width) / m_height;
|
2016-01-24 17:20:03 +01:00
|
|
|
Entity camera_entity = m_scene->getCameraEntity(m_applied_camera);
|
|
|
|
Matrix camera_matrix = universe.getMatrix(camera_entity);
|
|
|
|
Matrix view_matrix = camera_matrix;
|
|
|
|
view_matrix.fastInverse();
|
2015-09-11 03:58:02 +02:00
|
|
|
projection_matrix.setPerspective(
|
|
|
|
Math::degreesToRadians(fov), ratio, near_plane, far_plane);
|
2016-01-24 17:20:03 +01:00
|
|
|
Matrix inv_projection = projection_matrix;
|
|
|
|
inv_projection.inverse();
|
|
|
|
Matrix inv_view_proj = projection_matrix * view_matrix;
|
|
|
|
inv_view_proj.inverse();
|
2015-09-11 03:58:02 +02:00
|
|
|
|
2016-01-24 17:20:03 +01:00
|
|
|
bgfx::setUniform(m_cam_inv_proj_uniform, &inv_projection.m11);
|
|
|
|
bgfx::setUniform(m_cam_inv_viewproj_uniform, &inv_view_proj.m11);
|
2016-01-25 22:22:31 +01:00
|
|
|
bgfx::setUniform(m_cam_view_uniform, &view_matrix.m11);
|
2016-02-01 15:13:00 +01:00
|
|
|
bgfx::setUniform(m_cam_proj_uniform, &projection_matrix.m11);
|
|
|
|
bgfx::setUniform(m_cam_inv_view_uniform, &camera_matrix.m11);
|
|
|
|
bgfx::setUniform(m_cam_params, &Vec4(near_plane, far_plane, fov, ratio));
|
2015-09-11 03:58:02 +02:00
|
|
|
}
|
|
|
|
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2015-09-11 03:58:02 +02:00
|
|
|
bgfx::setState(m_render_state | material->getRenderStates());
|
2015-08-27 23:18:49 +02:00
|
|
|
bgfx::setVertexBuffer(&vb);
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
++m_stats.m_instance_count;
|
|
|
|
m_stats.m_triangle_count += 2;
|
2015-10-24 15:27:48 +02:00
|
|
|
bgfx::submit(m_view_idx, material->getShaderInstance().m_program_handles[m_pass_idx]);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-09-07 01:10:24 +02:00
|
|
|
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2015-11-11 21:54:25 +01:00
|
|
|
void renderAll(const Frustum& frustum, int64 layer_mask, bool render_grass)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
|
2015-08-27 23:18:49 +02:00
|
|
|
if (m_applied_camera < 0) return;
|
|
|
|
|
|
|
|
m_tmp_grasses.clear();
|
|
|
|
m_tmp_meshes.clear();
|
|
|
|
m_tmp_terrains.clear();
|
|
|
|
|
|
|
|
m_scene->getRenderableInfos(frustum, m_tmp_meshes, layer_mask);
|
2015-10-18 11:53:32 +02:00
|
|
|
Entity camera_entity = m_scene->getCameraEntity(m_applied_camera);
|
|
|
|
Vec3 camera_pos = m_scene->getUniverse().getPosition(camera_entity);
|
|
|
|
LIFOAllocator& frame_allocator = m_renderer.getFrameAllocator();
|
|
|
|
m_scene->getTerrainInfos(m_tmp_terrains, layer_mask, camera_pos, frame_allocator);
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
m_is_current_light_global = true;
|
|
|
|
m_current_light = m_scene->getActiveGlobalLight();
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2016-01-22 18:12:59 +01:00
|
|
|
if (m_current_light != INVALID_COMPONENT)
|
|
|
|
{
|
|
|
|
Universe& universe = m_scene->getUniverse();
|
|
|
|
Entity light_entity = m_scene->getGlobalLightEntity(m_current_light);
|
|
|
|
Vec3 light_dir = universe.getRotation(light_entity) * Vec3(0, 0, 1);
|
|
|
|
Vec3 diffuse_color = m_scene->getGlobalLightColor(m_current_light) *
|
|
|
|
m_scene->getGlobalLightIntensity(m_current_light);
|
|
|
|
Vec3 ambient_color = m_scene->getLightAmbientColor(m_current_light) *
|
|
|
|
m_scene->getLightAmbientIntensity(m_current_light);
|
|
|
|
Vec3 fog_color = m_scene->getFogColor(m_current_light);
|
|
|
|
float fog_density = m_scene->getFogDensity(m_current_light);
|
2016-01-28 21:44:35 +01:00
|
|
|
Vec3 specular = m_scene->getGlobalLightSpecular(m_current_light);
|
2016-02-10 12:09:09 +01:00
|
|
|
float specular_intensity = m_scene->getGlobalLightSpecularIntensity(m_current_light);
|
|
|
|
specular *= specular_intensity * specular_intensity;
|
2016-01-28 21:44:35 +01:00
|
|
|
m_directional_light_uniforms.diffuse_light_color.set(diffuse_color, 1);
|
2016-01-22 18:12:59 +01:00
|
|
|
m_directional_light_uniforms.ambient_light_color.set(ambient_color, 1);
|
|
|
|
m_directional_light_uniforms.light_dir_fov.set(light_dir, 0);
|
|
|
|
fog_density *= fog_density * fog_density;
|
|
|
|
m_directional_light_uniforms.fog_color_density.set(fog_color, fog_density);
|
2016-01-28 21:44:35 +01:00
|
|
|
m_directional_light_uniforms.specular.set(specular, 0);
|
2016-01-22 18:12:59 +01:00
|
|
|
m_directional_light_uniforms.fog_params.set(m_scene->getFogBottom(m_current_light),
|
|
|
|
m_scene->getFogHeight(m_current_light),
|
|
|
|
0,
|
|
|
|
0);
|
|
|
|
}
|
|
|
|
|
2015-09-27 23:13:40 +02:00
|
|
|
if (render_grass)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-09-27 23:13:40 +02:00
|
|
|
m_scene->getGrassInfos(frustum, m_tmp_grasses, layer_mask, m_applied_camera);
|
2015-08-27 23:18:49 +02:00
|
|
|
renderGrasses(m_tmp_grasses);
|
2015-02-14 00:13:34 +01:00
|
|
|
}
|
2016-01-30 10:06:58 +01:00
|
|
|
renderTerrains(m_tmp_terrains);
|
|
|
|
renderMeshes(m_tmp_meshes);
|
2015-09-27 23:13:40 +02:00
|
|
|
|
2015-09-03 14:25:12 +02:00
|
|
|
m_current_light = -1;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void toggleStats() override
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
m_debug_flags ^= BGFX_DEBUG_STATS;
|
|
|
|
bgfx::setDebug(m_debug_flags);
|
|
|
|
}
|
2015-02-18 00:52:03 +01:00
|
|
|
|
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void setWindowHandle(void* data) override
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-09-27 23:13:40 +02:00
|
|
|
m_default_framebuffer =
|
2015-11-11 23:25:44 +01:00
|
|
|
LUMIX_NEW(m_allocator, FrameBuffer)("default", m_width, m_height, data);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-02-28 10:06:50 +01:00
|
|
|
|
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void renderModel(Model& model, const Matrix& mtx) override
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
for (int i = 0; i < model.getMeshCount(); ++i)
|
2014-11-16 19:31:51 +01:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
auto& mesh = model.getMesh(i);
|
2016-01-22 18:02:07 +01:00
|
|
|
int instance_idx = mesh.instance_idx;
|
2015-12-10 20:27:51 +01:00
|
|
|
if (instance_idx == -1)
|
|
|
|
{
|
|
|
|
instance_idx = m_instance_data_idx;
|
|
|
|
m_instance_data_idx = (m_instance_data_idx + 1) % lengthOf(m_instances_data);
|
|
|
|
if (m_instances_data[instance_idx].buffer)
|
|
|
|
{
|
|
|
|
finishInstances(instance_idx);
|
|
|
|
}
|
2016-01-22 18:02:07 +01:00
|
|
|
mesh.instance_idx = instance_idx;
|
2015-12-10 20:27:51 +01:00
|
|
|
}
|
|
|
|
InstanceData& data = m_instances_data[instance_idx];
|
|
|
|
if (!data.buffer)
|
|
|
|
{
|
|
|
|
data.buffer =
|
|
|
|
bgfx::allocInstanceDataBuffer(InstanceData::MAX_INSTANCE_COUNT, sizeof(Matrix));
|
|
|
|
data.instance_count = 0;
|
|
|
|
data.mesh = &mesh;
|
|
|
|
data.model = &model;
|
|
|
|
}
|
|
|
|
Matrix* mtcs = (Matrix*)data.buffer->data;
|
|
|
|
mtcs[data.instance_count] = mtx;
|
|
|
|
++data.instance_count;
|
|
|
|
|
|
|
|
if (data.instance_count == InstanceData::MAX_INSTANCE_COUNT)
|
|
|
|
{
|
|
|
|
finishInstances(instance_idx);
|
|
|
|
}
|
2014-11-16 19:31:51 +01:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-02-14 14:23:12 +01:00
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void setPoseUniform(const RenderableMesh& renderable_mesh) const
|
|
|
|
{
|
2016-02-03 04:37:09 +01:00
|
|
|
Matrix bone_mtx[128];
|
2015-12-10 20:27:51 +01:00
|
|
|
|
|
|
|
Renderable* renderable = m_scene->getRenderable(renderable_mesh.renderable);
|
|
|
|
const Pose& pose = *renderable->pose;
|
|
|
|
const Model& model = *renderable->model;
|
2015-07-23 23:17:51 +02:00
|
|
|
Vec3* poss = pose.getPositions();
|
|
|
|
Quat* rots = pose.getRotations();
|
2015-07-13 09:17:09 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
ASSERT(pose.getCount() <= lengthOf(bone_mtx));
|
2015-10-24 14:05:24 +02:00
|
|
|
for (int bone_index = 0, bone_count = pose.getCount(); bone_index < bone_count;
|
2015-07-23 23:17:51 +02:00
|
|
|
++bone_index)
|
2014-11-16 19:31:51 +01:00
|
|
|
{
|
2016-02-04 00:39:00 +01:00
|
|
|
auto& bone = model.getBone(bone_index);
|
2015-07-23 23:17:51 +02:00
|
|
|
rots[bone_index].toMatrix(bone_mtx[bone_index]);
|
|
|
|
bone_mtx[bone_index].translate(poss[bone_index]);
|
2016-02-04 00:39:00 +01:00
|
|
|
bone_mtx[bone_index] = bone_mtx[bone_index] * bone.inv_bind_matrix;
|
2014-11-16 19:31:51 +01:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setUniform(m_bone_matrices_uniform, bone_mtx, pose.getCount());
|
|
|
|
}
|
2015-02-14 14:23:12 +01:00
|
|
|
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
void renderSkinnedMesh(const Renderable& renderable, const RenderableMesh& info)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
const Mesh& mesh = *info.mesh;
|
2016-01-22 18:02:07 +01:00
|
|
|
Material* material = mesh.material;
|
2015-07-23 23:17:51 +02:00
|
|
|
|
|
|
|
setPoseUniform(info);
|
|
|
|
setMaterial(material);
|
2015-12-10 20:27:51 +01:00
|
|
|
bgfx::setTransform(&renderable.matrix);
|
|
|
|
bgfx::setVertexBuffer(renderable.model->getVerticesHandle(),
|
2016-01-22 18:02:07 +01:00
|
|
|
mesh.attribute_array_offset / mesh.vertex_def.getStride(),
|
|
|
|
mesh.attribute_array_size / mesh.vertex_def.getStride());
|
2015-10-24 14:05:24 +02:00
|
|
|
bgfx::setIndexBuffer(
|
2016-01-22 18:02:07 +01:00
|
|
|
renderable.model->getIndicesHandle(), mesh.indices_offset, mesh.indices_count);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setState(m_render_state | material->getRenderStates());
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
++m_stats.m_instance_count;
|
|
|
|
m_stats.m_triangle_count += mesh.indices_count / 3;
|
|
|
|
bgfx::submit(m_view_idx, mesh.material->getShaderInstance().m_program_handles[m_pass_idx]);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-11-16 19:31:51 +01:00
|
|
|
|
2015-05-07 00:55:50 +02:00
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void setScissor(int x, int y, int width, int height) override
|
2015-08-15 09:56:37 +02:00
|
|
|
{
|
|
|
|
bgfx::setScissor(x, y, width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-14 00:25:08 +01:00
|
|
|
void setTexture(int slot, bgfx::TextureHandle texture, bgfx::UniformHandle uniform) override
|
2015-08-14 22:12:51 +02:00
|
|
|
{
|
2015-11-14 00:25:08 +01:00
|
|
|
bgfx::setTexture(slot, uniform, texture);
|
2015-08-14 22:12:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void render(TransientGeometry& geom,
|
2015-10-15 20:53:13 +02:00
|
|
|
const Matrix& mtx,
|
2015-10-24 14:05:24 +02:00
|
|
|
int first_index,
|
|
|
|
int num_indices,
|
2015-11-11 21:54:25 +01:00
|
|
|
uint64 render_states,
|
2015-10-15 20:53:13 +02:00
|
|
|
bgfx::ProgramHandle program_handle) override
|
|
|
|
{
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2015-10-15 20:53:13 +02:00
|
|
|
bgfx::setState(m_render_state | render_states);
|
|
|
|
bgfx::setTransform(&mtx.m11);
|
|
|
|
bgfx::setVertexBuffer(&geom.getVertexBuffer());
|
2015-10-24 14:05:24 +02:00
|
|
|
bgfx::setIndexBuffer(&geom.getIndexBuffer(), first_index, num_indices);
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
++m_stats.m_instance_count;
|
|
|
|
m_stats.m_triangle_count += num_indices / 3;
|
2015-10-15 20:53:13 +02:00
|
|
|
bgfx::submit(m_view_idx, program_handle);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
void renderRigidMesh(const Renderable& renderable, const RenderableMesh& info)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-01-22 18:02:07 +01:00
|
|
|
int instance_idx = info.mesh->instance_idx;
|
2015-07-23 23:17:51 +02:00
|
|
|
if (instance_idx == -1)
|
2015-07-12 17:14:43 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
instance_idx = m_instance_data_idx;
|
2015-10-24 15:27:48 +02:00
|
|
|
m_instance_data_idx = (m_instance_data_idx + 1) % lengthOf(m_instances_data);
|
2015-12-10 20:27:51 +01:00
|
|
|
if (m_instances_data[instance_idx].buffer)
|
2015-07-12 17:14:43 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
finishInstances(instance_idx);
|
2015-07-12 17:14:43 +02:00
|
|
|
}
|
2016-01-22 18:02:07 +01:00
|
|
|
info.mesh->instance_idx = instance_idx;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
InstanceData& data = m_instances_data[instance_idx];
|
2015-12-10 20:27:51 +01:00
|
|
|
if (!data.buffer)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
data.buffer =
|
2015-10-24 15:27:48 +02:00
|
|
|
bgfx::allocInstanceDataBuffer(InstanceData::MAX_INSTANCE_COUNT, sizeof(Matrix));
|
2015-12-10 20:27:51 +01:00
|
|
|
data.instance_count = 0;
|
|
|
|
data.mesh = info.mesh;
|
|
|
|
data.model = renderable.model;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-12-10 20:27:51 +01:00
|
|
|
Matrix* mtcs = (Matrix*)data.buffer->data;
|
|
|
|
mtcs[data.instance_count] = renderable.matrix;
|
|
|
|
++data.instance_count;
|
2015-09-28 00:51:28 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
if (data.instance_count == InstanceData::MAX_INSTANCE_COUNT)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-10-24 15:27:48 +02:00
|
|
|
finishInstances(instance_idx);
|
2015-07-12 17:14:43 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-07-12 17:14:43 +02:00
|
|
|
|
|
|
|
|
2015-09-04 14:00:28 +02:00
|
|
|
void setMaterial(Material* material)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-02-06 00:44:43 +01:00
|
|
|
if (!material->isReady()) return;
|
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
if (m_is_current_light_global)
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
2015-09-02 11:14:42 +02:00
|
|
|
setDirectionalLightUniforms(m_current_light);
|
2015-09-04 14:00:28 +02:00
|
|
|
}
|
2015-09-02 11:14:42 +02:00
|
|
|
else
|
2015-09-04 14:00:28 +02:00
|
|
|
{
|
|
|
|
setPointLightUniforms(material, m_current_light);
|
|
|
|
}
|
2015-09-02 11:14:42 +02:00
|
|
|
|
2016-02-09 19:21:00 +01:00
|
|
|
Shader* shader = material->getShader();
|
|
|
|
for (int i = 0; i < shader->getUniformCount(); ++i)
|
2014-10-17 01:21:59 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
const Material::Uniform& uniform = material->getUniform(i);
|
2016-02-09 19:21:00 +01:00
|
|
|
const Shader::Uniform& shader_uniform = shader->getUniform(i);
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2016-02-09 19:21:00 +01:00
|
|
|
switch (shader_uniform.type)
|
2015-02-18 00:52:03 +01:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::FLOAT:
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2016-02-09 19:21:00 +01:00
|
|
|
Vec4 v(uniform.float_value, 0, 0, 0);
|
|
|
|
bgfx::setUniform(shader_uniform.handle, &v);
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
break;
|
2016-02-09 19:21:00 +01:00
|
|
|
case Shader::Uniform::VEC3:
|
|
|
|
case Shader::Uniform::COLOR:
|
|
|
|
{
|
|
|
|
Vec4 v(*(Vec3*)uniform.vec3, 0);
|
|
|
|
bgfx::setUniform(shader_uniform.handle, &v);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
case Shader::Uniform::TIME:
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
Vec4 v(m_scene->getTime(), 0, 0, 0);
|
2016-02-09 19:21:00 +01:00
|
|
|
bgfx::setUniform(shader_uniform.handle, &v);
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
break;
|
2015-10-24 15:27:48 +02:00
|
|
|
default: ASSERT(false); break;
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
|
|
|
}
|
2015-02-14 14:23:12 +01:00
|
|
|
|
2016-02-10 14:32:40 +01:00
|
|
|
for (int i = 0; i < shader->getTextureSlotCount(); ++i)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
Texture* texture = material->getTexture(i);
|
2015-10-07 22:40:11 +02:00
|
|
|
if (!texture) continue;
|
|
|
|
|
|
|
|
bgfx::setTexture(
|
|
|
|
i, shader->getTextureSlot(i).m_uniform_handle, texture->getTextureHandle());
|
2015-07-20 23:43:10 +02:00
|
|
|
}
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2015-10-06 17:00:52 +02:00
|
|
|
Vec4 specular_shininess(material->getSpecular(), material->getShininess());
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setUniform(m_specular_shininess_uniform, &specular_shininess);
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2015-10-07 17:59:49 +02:00
|
|
|
if (m_is_current_light_global && !m_is_rendering_in_shadowmap && m_global_light_shadowmap)
|
2015-10-05 22:44:03 +02:00
|
|
|
{
|
2015-10-26 23:39:43 +01:00
|
|
|
auto handle = m_global_light_shadowmap->getRenderbufferHandle(0);
|
2015-10-06 17:00:52 +02:00
|
|
|
bgfx::setTexture(shader->getTextureSlotCount(), m_tex_shadowmap_uniform, handle);
|
2015-10-05 22:44:03 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-02-14 14:23:12 +01:00
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void renderTerrain(const TerrainInfo& info)
|
|
|
|
{
|
|
|
|
auto& inst = m_terrain_instances[info.m_index];
|
2015-10-24 15:27:48 +02:00
|
|
|
if ((inst.m_count > 0 && inst.m_infos[0]->m_terrain != info.m_terrain) ||
|
2015-07-23 23:17:51 +02:00
|
|
|
inst.m_count == lengthOf(inst.m_infos))
|
|
|
|
{
|
|
|
|
finishTerrainInstances(info.m_index);
|
|
|
|
}
|
|
|
|
inst.m_infos[inst.m_count] = &info;
|
|
|
|
++inst.m_count;
|
|
|
|
}
|
2015-02-27 23:56:06 +01:00
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void finishTerrainInstances(int index)
|
|
|
|
{
|
2015-10-06 17:00:52 +02:00
|
|
|
if (m_terrain_instances[index].m_count == 0) return;
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
const TerrainInfo& info = *m_terrain_instances[index].m_infos[0];
|
|
|
|
Material* material = info.m_terrain->getMaterial();
|
2015-10-06 17:00:52 +02:00
|
|
|
if (!material->isReady()) return;
|
|
|
|
|
2015-08-27 23:18:49 +02:00
|
|
|
Texture* detail_texture = info.m_terrain->getDetailTexture();
|
2015-10-06 17:00:52 +02:00
|
|
|
if (!detail_texture) return;
|
2015-10-07 17:48:34 +02:00
|
|
|
Texture* splat_texture = info.m_terrain->getSplatmap();
|
|
|
|
if (!splat_texture) return;
|
2015-08-27 23:18:49 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
Matrix inv_world_matrix;
|
|
|
|
inv_world_matrix = info.m_world_matrix;
|
|
|
|
inv_world_matrix.fastInverse();
|
2015-10-24 15:27:48 +02:00
|
|
|
Vec3 camera_pos =
|
|
|
|
m_scene->getUniverse().getPosition(m_scene->getCameraEntity(m_applied_camera));
|
2015-07-24 08:42:35 +02:00
|
|
|
|
2015-11-14 00:25:08 +01:00
|
|
|
Vec4 rel_cam_pos(
|
|
|
|
inv_world_matrix.multiplyPosition(camera_pos) / info.m_terrain->getXZScale(), 1);
|
|
|
|
Vec4 terrain_scale(info.m_terrain->getScale(), 0);
|
2015-07-23 23:17:51 +02:00
|
|
|
const Mesh& mesh = *info.m_terrain->getMesh();
|
|
|
|
|
2015-08-24 21:00:35 +02:00
|
|
|
Vec4 terrain_params(info.m_terrain->getRootSize(),
|
2015-10-24 15:27:48 +02:00
|
|
|
(float)detail_texture->getWidth(),
|
|
|
|
(float)detail_texture->getAtlasSize(),
|
|
|
|
(float)splat_texture->getWidth());
|
2015-08-24 21:00:35 +02:00
|
|
|
bgfx::setUniform(m_terrain_params_uniform, &terrain_params);
|
2015-11-14 00:25:08 +01:00
|
|
|
bgfx::setUniform(m_rel_camera_pos_uniform, &rel_cam_pos);
|
|
|
|
bgfx::setUniform(m_terrain_scale_uniform, &terrain_scale);
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setUniform(m_terrain_matrix_uniform, &info.m_world_matrix.m11);
|
|
|
|
|
|
|
|
setMaterial(material);
|
|
|
|
|
2015-08-27 23:18:49 +02:00
|
|
|
struct TerrainInstanceData
|
|
|
|
{
|
|
|
|
Vec4 m_quad_min_and_size;
|
|
|
|
Vec4 m_morph_const;
|
|
|
|
};
|
2015-10-07 22:40:11 +02:00
|
|
|
const bgfx::InstanceDataBuffer* instance_buffer = bgfx::allocInstanceDataBuffer(
|
|
|
|
m_terrain_instances[index].m_count, sizeof(TerrainInstanceData));
|
2015-10-06 17:00:52 +02:00
|
|
|
TerrainInstanceData* instance_data = (TerrainInstanceData*)instance_buffer->data;
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
for (int i = 0; i < m_terrain_instances[index].m_count; ++i)
|
|
|
|
{
|
|
|
|
const TerrainInfo& info = *m_terrain_instances[index].m_infos[i];
|
|
|
|
instance_data[i].m_quad_min_and_size.set(
|
|
|
|
info.m_min.x, info.m_min.y, info.m_min.z, info.m_size);
|
2015-10-07 22:40:11 +02:00
|
|
|
instance_data[i].m_morph_const.set(
|
|
|
|
info.m_morph_const.x, info.m_morph_const.y, info.m_morph_const.z, 0);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
bgfx::setVertexBuffer(info.m_terrain->getVerticesHandle());
|
2016-01-22 18:02:07 +01:00
|
|
|
int mesh_part_indices_count = mesh.indices_count / 4;
|
2015-10-06 17:00:52 +02:00
|
|
|
bgfx::setIndexBuffer(info.m_terrain->getIndicesHandle(),
|
2015-10-07 22:40:11 +02:00
|
|
|
info.m_index * mesh_part_indices_count,
|
|
|
|
mesh_part_indices_count);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2016-01-22 18:02:07 +01:00
|
|
|
bgfx::setState(m_render_state | mesh.material->getRenderStates());
|
2015-10-07 22:40:11 +02:00
|
|
|
bgfx::setInstanceDataBuffer(instance_buffer, m_terrain_instances[index].m_count);
|
2015-10-06 17:00:52 +02:00
|
|
|
auto shader_instance = material->getShaderInstance().m_program_handles[m_pass_idx];
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
m_stats.m_instance_count += m_terrain_instances[index].m_count;
|
|
|
|
m_stats.m_triangle_count += m_terrain_instances[index].m_count * mesh_part_indices_count;
|
2015-10-06 17:00:52 +02:00
|
|
|
bgfx::submit(m_view_idx, shader_instance);
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
m_terrain_instances[index].m_count = 0;
|
|
|
|
}
|
|
|
|
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void renderGrass(const GrassInfo& grass)
|
|
|
|
{
|
|
|
|
const bgfx::InstanceDataBuffer* idb =
|
|
|
|
bgfx::allocInstanceDataBuffer(grass.m_matrix_count, sizeof(Matrix));
|
2015-11-12 17:32:12 +01:00
|
|
|
copyMemory(idb->data, &grass.m_matrices[0], grass.m_matrix_count * sizeof(Matrix));
|
2015-07-23 23:17:51 +02:00
|
|
|
const Mesh& mesh = grass.m_model->getMesh(0);
|
2016-01-22 18:02:07 +01:00
|
|
|
Material* material = mesh.material;
|
2015-07-23 23:17:51 +02:00
|
|
|
|
|
|
|
setMaterial(material);
|
2015-10-06 17:00:52 +02:00
|
|
|
bgfx::setVertexBuffer(grass.m_model->getVerticesHandle(),
|
2016-01-22 18:02:07 +01:00
|
|
|
mesh.attribute_array_offset / mesh.vertex_def.getStride(),
|
|
|
|
mesh.attribute_array_size / mesh.vertex_def.getStride());
|
2015-10-24 15:27:48 +02:00
|
|
|
bgfx::setIndexBuffer(
|
2016-01-22 18:02:07 +01:00
|
|
|
grass.m_model->getIndicesHandle(), mesh.indices_offset, mesh.indices_count);
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setStencil(m_stencil, BGFX_STENCIL_NONE);
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::setState(m_render_state | material->getRenderStates());
|
|
|
|
bgfx::setInstanceDataBuffer(idb, grass.m_matrix_count);
|
2016-01-28 15:19:56 +01:00
|
|
|
++m_stats.m_draw_call_count;
|
|
|
|
m_stats.m_instance_count += grass.m_matrix_count;
|
|
|
|
m_stats.m_triangle_count += grass.m_matrix_count * mesh.indices_count;
|
2015-08-04 22:34:27 +02:00
|
|
|
bgfx::submit(m_view_idx, material->getShaderInstance().m_program_handles[m_pass_idx]);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
|
|
|
|
void renderGrasses(const Array<GrassInfo>& grasses)
|
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
|
|
|
for (const auto& grass : grasses)
|
2015-02-14 14:23:12 +01:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
renderGrass(grass);
|
2015-02-14 14:23:12 +01:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-07-04 15:22:28 +02:00
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void renderTerrains(const Array<const TerrainInfo*>& terrains)
|
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2015-12-20 17:16:21 +01:00
|
|
|
PROFILE_INT("terrain patches", terrains.size());
|
2015-07-23 23:17:51 +02:00
|
|
|
for (auto* info : terrains)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
renderTerrain(*info);
|
2014-05-20 23:35:09 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
for (int i = 0; i < lengthOf(m_terrain_instances); ++i)
|
|
|
|
{
|
|
|
|
finishTerrainInstances(i);
|
|
|
|
}
|
|
|
|
}
|
2015-02-14 00:13:34 +01:00
|
|
|
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2015-12-10 20:27:51 +01:00
|
|
|
void renderMeshes(const Array<RenderableMesh>& meshes)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2015-12-10 20:27:51 +01:00
|
|
|
if (meshes.empty()) return;
|
|
|
|
|
|
|
|
Renderable* renderables = m_scene->getRenderables();
|
2015-12-13 10:46:53 +01:00
|
|
|
PROFILE_INT("mesh count", meshes.size());
|
2015-12-10 20:27:51 +01:00
|
|
|
for (auto& mesh : meshes)
|
2015-05-16 13:17:20 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
Renderable& renderable = renderables[mesh.renderable];
|
|
|
|
if (renderable.pose && renderable.pose->getCount() > 0)
|
2015-07-13 09:17:09 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
renderSkinnedMesh(renderable, mesh);
|
2015-07-13 09:17:09 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
renderRigidMesh(renderable, mesh);
|
2015-07-13 09:17:09 +02:00
|
|
|
}
|
2015-05-16 13:17:20 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
finishInstances();
|
|
|
|
}
|
2015-07-04 15:22:28 +02:00
|
|
|
|
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void setViewport(int x, int y, int w, int h) override
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2015-09-20 17:30:37 +02:00
|
|
|
m_view_x = x;
|
|
|
|
m_view_y = y;
|
2015-08-25 14:53:38 +02:00
|
|
|
if (m_width == w && m_height == h) return;
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
if (m_default_framebuffer)
|
2014-05-20 23:35:09 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
m_default_framebuffer->resize(w, h);
|
2016-01-24 17:20:03 +01:00
|
|
|
}
|
|
|
|
for (auto& i : m_framebuffers)
|
|
|
|
{
|
2016-02-01 16:38:27 +01:00
|
|
|
auto size_ratio = i->getSizeRatio();
|
|
|
|
if (size_ratio.x > 0 || size_ratio.y > 0)
|
|
|
|
{
|
|
|
|
i->resize(int(w * size_ratio.x), int(h * size_ratio.y));
|
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
|
|
|
m_width = w;
|
|
|
|
m_height = h;
|
|
|
|
}
|
2015-07-04 15:22:28 +02:00
|
|
|
|
|
|
|
|
2015-11-10 22:25:36 +01:00
|
|
|
void render() override
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
|
|
|
PROFILE_FUNCTION();
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
if (!isReady()) return;
|
2015-05-16 13:17:20 +02:00
|
|
|
|
2016-01-28 15:19:56 +01:00
|
|
|
m_stats = {};
|
2016-02-10 14:32:40 +01:00
|
|
|
m_render_state = BGFX_STATE_RGB_WRITE | BGFX_STATE_ALPHA_WRITE | BGFX_STATE_DEPTH_WRITE | BGFX_STATE_MSAA;
|
2015-12-10 23:59:10 +01:00
|
|
|
m_applied_camera = INVALID_COMPONENT;
|
2015-10-07 17:59:49 +02:00
|
|
|
m_global_light_shadowmap = nullptr;
|
2016-02-10 00:00:21 +01:00
|
|
|
m_stencil = BGFX_STENCIL_NONE;
|
2015-09-21 22:55:15 +02:00
|
|
|
m_render_state |= m_is_wireframe ? BGFX_STATE_PT_LINESTRIP : 0;
|
2015-07-31 22:22:37 +02:00
|
|
|
m_view_idx = m_renderer.getViewCounter();
|
2015-07-23 23:17:51 +02:00
|
|
|
m_pass_idx = -1;
|
|
|
|
m_current_framebuffer = m_default_framebuffer;
|
2015-09-22 23:58:11 +02:00
|
|
|
m_current_light = -1;
|
2015-08-12 21:54:47 +02:00
|
|
|
m_view2pass_map.assign(0xFF);
|
2015-07-23 23:17:51 +02:00
|
|
|
m_instance_data_idx = 0;
|
2015-09-02 11:14:42 +02:00
|
|
|
m_point_light_shadowmaps.clear();
|
2015-07-23 23:17:51 +02:00
|
|
|
for (int i = 0; i < lengthOf(m_terrain_instances); ++i)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
m_terrain_instances[i].m_count = 0;
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
for (int i = 0; i < lengthOf(m_instances_data); ++i)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-12-10 20:27:51 +01:00
|
|
|
m_instances_data[i].buffer = nullptr;
|
|
|
|
m_instances_data[i].instance_count = 0;
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
if (lua_getglobal(m_lua_state, "render") == LUA_TFUNCTION)
|
2015-05-15 22:38:34 +02:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
lua_pushlightuserdata(m_lua_state, this);
|
|
|
|
if (lua_pcall(m_lua_state, 1, 0, 0) != LUA_OK)
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
g_log_error.log("lua") << lua_tostring(m_lua_state, -1);
|
|
|
|
lua_pop(m_lua_state, 1);
|
2015-07-04 15:22:28 +02:00
|
|
|
}
|
2015-05-15 22:38:34 +02:00
|
|
|
}
|
2015-08-27 23:18:49 +02:00
|
|
|
else
|
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
lua_pop(m_lua_state, 1);
|
2015-08-27 23:18:49 +02:00
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
finishInstances();
|
2015-05-15 22:38:34 +02:00
|
|
|
|
2015-09-26 19:59:14 +02:00
|
|
|
m_renderer.getFrameAllocator().clear();
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-05-15 22:38:34 +02:00
|
|
|
|
2015-07-04 15:22:28 +02:00
|
|
|
|
2016-01-12 19:37:00 +01:00
|
|
|
void exposeCustomCommandToLua(const CustomCommandHandler& handler)
|
|
|
|
{
|
|
|
|
if (!m_lua_state) return;
|
2016-01-12 13:52:14 +01:00
|
|
|
|
2016-01-12 19:37:00 +01:00
|
|
|
char tmp[1024];
|
|
|
|
copyString(tmp, "function ");
|
|
|
|
catString(tmp, handler.name);
|
|
|
|
catString(tmp, "(pipeline) executeCustomCommand(pipeline, \"");
|
|
|
|
catString(tmp, handler.name);
|
|
|
|
catString(tmp, "\") end");
|
2016-01-12 13:52:14 +01:00
|
|
|
|
2016-01-12 19:37:00 +01:00
|
|
|
bool errors = luaL_loadbuffer(m_lua_state, tmp, stringLength(tmp), nullptr) != LUA_OK;
|
|
|
|
errors = errors || lua_pcall(m_lua_state, 0, LUA_MULTRET, 0) != LUA_OK;
|
|
|
|
|
|
|
|
if (errors)
|
|
|
|
{
|
|
|
|
g_log_error.log("pipeline") << lua_tostring(m_lua_state, -1);
|
|
|
|
lua_pop(m_lua_state, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
int loadMaterial(const char* path)
|
|
|
|
{
|
|
|
|
ResourceManagerBase& material_manager = m_renderer.getMaterialManager();
|
|
|
|
auto* material = static_cast<Material*>(material_manager.load(Lumix::Path(path)));
|
|
|
|
|
|
|
|
m_materials.push(material);
|
|
|
|
return m_materials.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int createUniform(const char* name)
|
|
|
|
{
|
|
|
|
bgfx::UniformHandle handle = bgfx::createUniform(name, bgfx::UniformType::Int1);
|
|
|
|
m_uniforms.push(handle);
|
|
|
|
return m_uniforms.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-30 10:06:58 +01:00
|
|
|
int createVec4ArrayUniform(const char* name, int num)
|
|
|
|
{
|
|
|
|
bgfx::UniformHandle handle = bgfx::createUniform(name, bgfx::UniformType::Vec4, num);
|
|
|
|
m_uniforms.push(handle);
|
|
|
|
return m_uniforms.size() - 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2016-01-15 00:05:53 +01:00
|
|
|
bool hasScene()
|
|
|
|
{
|
|
|
|
return m_scene != nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool cameraExists(const char* slot_name)
|
|
|
|
{
|
|
|
|
return m_scene->getCameraInSlot(slot_name) != INVALID_ENTITY;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void enableBlending(const char* mode)
|
|
|
|
{
|
|
|
|
uint64 mode_value = 0;
|
|
|
|
if (compareString(mode, "alpha") == 0) mode_value = BGFX_STATE_BLEND_ALPHA;
|
|
|
|
else if (compareString(mode, "add") == 0) mode_value = BGFX_STATE_BLEND_ADD;
|
|
|
|
else if (compareString(mode, "multiply") == 0) mode_value = BGFX_STATE_BLEND_MULTIPLY;
|
|
|
|
|
|
|
|
m_render_state |= mode_value;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-02-10 00:00:21 +01:00
|
|
|
void clear(uint32 flags, uint32 color)
|
2016-01-15 00:05:53 +01:00
|
|
|
{
|
2016-02-10 00:00:21 +01:00
|
|
|
bgfx::setViewClear(m_view_idx, (uint16)flags, color, 1.0f, 0);
|
2016-01-15 00:05:53 +01:00
|
|
|
bgfx::touch(m_view_idx);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void renderModels(int64 layer_mask, bool is_point_light_render)
|
|
|
|
{
|
|
|
|
if (is_point_light_render)
|
|
|
|
{
|
|
|
|
renderPointLightInfluencedGeometry(m_camera_frustum, layer_mask);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
renderAll(m_camera_frustum, layer_mask, true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-01-12 19:37:00 +01:00
|
|
|
bool isReady() const override { return m_is_ready; }
|
2015-11-10 22:25:36 +01:00
|
|
|
void setScene(RenderScene* scene) override { m_scene = scene; }
|
|
|
|
void setWireframe(bool wireframe) override { m_is_wireframe = wireframe; }
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2016-01-24 17:20:03 +01:00
|
|
|
|
2015-08-27 23:18:49 +02:00
|
|
|
struct TerrainInstance
|
2015-07-04 15:22:28 +02:00
|
|
|
{
|
2015-07-23 23:17:51 +02:00
|
|
|
int m_count;
|
|
|
|
const TerrainInfo* m_infos[64];
|
|
|
|
};
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
struct PointLightShadowmap
|
|
|
|
{
|
|
|
|
ComponentIndex m_light;
|
|
|
|
FrameBuffer* m_framebuffer;
|
2015-09-04 14:00:28 +02:00
|
|
|
Matrix m_matrices[4];
|
2015-09-02 11:14:42 +02:00
|
|
|
};
|
|
|
|
|
2015-10-24 15:27:48 +02:00
|
|
|
|
|
|
|
struct BaseVertex
|
|
|
|
{
|
2016-01-24 17:20:03 +01:00
|
|
|
float x, y, z;
|
|
|
|
uint32 rgba;
|
|
|
|
float u;
|
|
|
|
float v;
|
2015-10-24 15:27:48 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-01-24 17:20:03 +01:00
|
|
|
bgfx::VertexDecl m_deferred_point_light_vertex_decl;
|
2015-10-24 15:27:48 +02:00
|
|
|
bgfx::VertexDecl m_base_vertex_decl;
|
2015-07-23 23:17:51 +02:00
|
|
|
TerrainInstance m_terrain_instances[4];
|
2015-11-11 21:54:25 +01:00
|
|
|
uint32 m_debug_flags;
|
|
|
|
uint8 m_view_idx;
|
2015-07-23 23:17:51 +02:00
|
|
|
int m_pass_idx;
|
2015-11-11 21:54:25 +01:00
|
|
|
StaticArray<uint8, 256> m_view2pass_map;
|
|
|
|
uint64 m_render_state;
|
2015-07-23 23:17:51 +02:00
|
|
|
IAllocator& m_allocator;
|
2016-01-12 13:52:14 +01:00
|
|
|
Lumix::Path m_path;
|
2015-07-23 23:17:51 +02:00
|
|
|
Renderer& m_renderer;
|
|
|
|
RenderScene* m_scene;
|
|
|
|
FrameBuffer* m_current_framebuffer;
|
|
|
|
FrameBuffer* m_default_framebuffer;
|
|
|
|
Array<FrameBuffer*> m_framebuffers;
|
|
|
|
Array<bgfx::UniformHandle> m_uniforms;
|
2015-09-11 03:58:02 +02:00
|
|
|
Array<Material*> m_materials;
|
2015-09-02 11:14:42 +02:00
|
|
|
Array<PointLightShadowmap> m_point_light_shadowmaps;
|
2015-10-05 22:44:03 +02:00
|
|
|
FrameBuffer* m_global_light_shadowmap;
|
2015-07-23 23:17:51 +02:00
|
|
|
InstanceData m_instances_data[128];
|
|
|
|
int m_instance_data_idx;
|
2015-08-27 23:18:49 +02:00
|
|
|
ComponentIndex m_applied_camera;
|
2015-09-02 11:14:42 +02:00
|
|
|
ComponentIndex m_current_light;
|
2016-01-26 10:27:31 +01:00
|
|
|
bgfx::VertexBufferHandle m_cube_vb;
|
|
|
|
bgfx::IndexBufferHandle m_cube_ib;
|
2015-09-02 11:14:42 +02:00
|
|
|
bool m_is_current_light_global;
|
2015-09-21 22:55:15 +02:00
|
|
|
bool m_is_wireframe;
|
2015-10-06 00:30:12 +02:00
|
|
|
bool m_is_rendering_in_shadowmap;
|
2016-01-12 13:52:14 +01:00
|
|
|
bool m_is_ready;
|
2015-08-27 23:18:49 +02:00
|
|
|
Frustum m_camera_frustum;
|
2015-07-23 23:17:51 +02:00
|
|
|
|
2015-09-05 13:08:47 +02:00
|
|
|
Matrix m_shadow_viewprojection[4];
|
2015-09-20 17:30:37 +02:00
|
|
|
int m_view_x;
|
|
|
|
int m_view_y;
|
2015-07-23 23:17:51 +02:00
|
|
|
int m_width;
|
|
|
|
int m_height;
|
2016-02-10 00:00:21 +01:00
|
|
|
uint32 m_stencil;
|
2015-11-04 22:43:54 +01:00
|
|
|
bgfx::VertexBufferHandle m_particle_vertex_buffer;
|
|
|
|
bgfx::IndexBufferHandle m_particle_index_buffer;
|
2016-01-12 19:37:00 +01:00
|
|
|
Array<CustomCommandHandler> m_custom_commands_handlers;
|
2015-12-10 20:27:51 +01:00
|
|
|
Array<RenderableMesh> m_tmp_meshes;
|
2015-07-23 23:17:51 +02:00
|
|
|
Array<const TerrainInfo*> m_tmp_terrains;
|
|
|
|
Array<GrassInfo> m_tmp_grasses;
|
2016-01-24 17:20:03 +01:00
|
|
|
Array<ComponentIndex> m_tmp_local_lights;
|
2016-01-22 18:12:59 +01:00
|
|
|
DirectionalLightUniforms m_directional_light_uniforms;
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::UniformHandle m_specular_shininess_uniform;
|
|
|
|
bgfx::UniformHandle m_bone_matrices_uniform;
|
|
|
|
bgfx::UniformHandle m_terrain_scale_uniform;
|
|
|
|
bgfx::UniformHandle m_rel_camera_pos_uniform;
|
2015-08-24 21:00:35 +02:00
|
|
|
bgfx::UniformHandle m_terrain_params_uniform;
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::UniformHandle m_fog_color_density_uniform;
|
2015-10-17 00:18:47 +02:00
|
|
|
bgfx::UniformHandle m_fog_params_uniform;
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::UniformHandle m_light_pos_radius_uniform;
|
2016-01-26 13:21:56 +01:00
|
|
|
bgfx::UniformHandle m_light_color_attenuation_uniform;
|
2015-07-23 23:17:51 +02:00
|
|
|
bgfx::UniformHandle m_ambient_color_uniform;
|
|
|
|
bgfx::UniformHandle m_light_dir_fov_uniform;
|
|
|
|
bgfx::UniformHandle m_shadowmap_matrices_uniform;
|
|
|
|
bgfx::UniformHandle m_light_specular_uniform;
|
|
|
|
bgfx::UniformHandle m_terrain_matrix_uniform;
|
2015-09-05 13:08:47 +02:00
|
|
|
bgfx::UniformHandle m_tex_shadowmap_uniform;
|
2015-09-11 03:58:02 +02:00
|
|
|
bgfx::UniformHandle m_cam_view_uniform;
|
2016-02-01 15:13:00 +01:00
|
|
|
bgfx::UniformHandle m_cam_proj_uniform;
|
|
|
|
bgfx::UniformHandle m_cam_params;
|
|
|
|
bgfx::UniformHandle m_cam_inv_view_uniform;
|
2015-09-11 03:58:02 +02:00
|
|
|
bgfx::UniformHandle m_cam_inv_proj_uniform;
|
2016-01-24 17:20:03 +01:00
|
|
|
bgfx::UniformHandle m_cam_inv_viewproj_uniform;
|
2015-11-01 12:00:10 +01:00
|
|
|
bgfx::UniformHandle m_texture_size_uniform;
|
2016-01-22 23:33:14 +01:00
|
|
|
int m_bind_framebuffer_texture_idx;
|
2015-10-24 15:27:48 +02:00
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
Material* m_debug_line_material;
|
2015-09-05 13:08:47 +02:00
|
|
|
int m_has_shadowmap_define_idx;
|
2015-07-23 23:17:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
Pipeline* Pipeline::create(Renderer& renderer, const Path& path, IAllocator& allocator)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
return LUMIX_NEW(allocator, PipelineImpl)(renderer, path, allocator);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-07-07 23:37:40 +02:00
|
|
|
|
|
|
|
|
2016-01-12 13:52:14 +01:00
|
|
|
void Pipeline::destroy(Pipeline* pipeline)
|
2015-07-23 23:17:51 +02:00
|
|
|
{
|
2016-01-12 13:52:14 +01:00
|
|
|
LUMIX_DELETE(static_cast<PipelineImpl*>(pipeline)->m_allocator, pipeline);
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-07-04 15:22:28 +02:00
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
namespace LuaAPI
|
|
|
|
{
|
2016-01-24 17:20:03 +01:00
|
|
|
|
|
|
|
|
|
|
|
int deferredLocalLightLoop(lua_State* L)
|
|
|
|
{
|
2016-01-25 14:07:12 +01:00
|
|
|
auto* p = LuaWrapper::checkArg<PipelineImpl*>(L, 1);
|
|
|
|
int material_index = LuaWrapper::checkArg<int>(L, 2);
|
|
|
|
LuaWrapper::checkTableArg(L, 3);
|
2016-01-24 17:20:03 +01:00
|
|
|
|
|
|
|
TextureBindData textures[16];
|
|
|
|
int texture_count = 0;
|
|
|
|
|
|
|
|
lua_pushnil(L);
|
|
|
|
while (lua_next(L, -2))
|
|
|
|
{
|
|
|
|
if (lua_istable(L, -1))
|
|
|
|
{
|
|
|
|
lua_rawgeti(L, -1, 1);
|
|
|
|
const char* fb_name = lua_tostring(L, -1);
|
|
|
|
lua_rawgeti(L, -2, 2);
|
|
|
|
int rb_idx = (int)lua_tointeger(L, -1);
|
|
|
|
lua_rawgeti(L, -3, 3);
|
|
|
|
int uniform_idx = (int)lua_tointeger(L, -1);
|
|
|
|
textures[texture_count].uniform = p->m_uniforms[uniform_idx];
|
|
|
|
textures[texture_count].texture = p->getFramebuffer(fb_name)->getRenderbufferHandle(rb_idx);
|
|
|
|
++texture_count;
|
|
|
|
lua_pop(L, 3);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
p->deferredLocalLightLoop(material_index, textures, texture_count);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2014-05-20 23:35:09 +02:00
|
|
|
|
2015-12-10 23:59:10 +01:00
|
|
|
void logError(const char* message)
|
|
|
|
{
|
2016-01-15 00:05:53 +01:00
|
|
|
g_log_error.log("renderer") << message;
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2014-05-20 23:35:09 +02:00
|
|
|
|
|
|
|
|
2016-01-30 10:06:58 +01:00
|
|
|
int setUniform(lua_State* L)
|
|
|
|
{
|
|
|
|
auto* pipeline = LuaWrapper::checkArg<PipelineImpl*>(L, 1);
|
|
|
|
int uniform_idx = LuaWrapper::checkArg<int>(L, 2);
|
|
|
|
LuaWrapper::checkTableArg(L, 3);
|
|
|
|
|
|
|
|
Vec4 tmp[64];
|
|
|
|
int len = Math::minValue((int)lua_rawlen(L, 3), lengthOf(tmp));
|
|
|
|
for (int i = 0; i < len; ++i)
|
|
|
|
{
|
|
|
|
if (lua_rawgeti(L, 3, 1 + i) == LUA_TTABLE)
|
|
|
|
{
|
|
|
|
if (lua_rawgeti(L, -1, 1) == LUA_TNUMBER) tmp[i].x = (float)lua_tonumber(L, -1);
|
|
|
|
if (lua_rawgeti(L, -2, 2) == LUA_TNUMBER) tmp[i].y = (float)lua_tonumber(L, -1);
|
|
|
|
if (lua_rawgeti(L, -3, 3) == LUA_TNUMBER) tmp[i].z = (float)lua_tonumber(L, -1);
|
|
|
|
if (lua_rawgeti(L, -4, 4) == LUA_TNUMBER) tmp[i].w = (float)lua_tonumber(L, -1);
|
|
|
|
lua_pop(L, 4);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (uniform_idx >= pipeline->m_uniforms.size()) luaL_argerror(L, 2, "unknown uniform");
|
|
|
|
|
|
|
|
bgfx::setUniform(pipeline->m_uniforms[uniform_idx], tmp, len);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-09-02 11:14:42 +02:00
|
|
|
int renderLocalLightsShadowmaps(lua_State* L)
|
|
|
|
{
|
2016-01-25 14:07:12 +01:00
|
|
|
auto* pipeline = LuaWrapper::checkArg<PipelineImpl*>(L, 1);
|
|
|
|
int64 layer_mask = LuaWrapper::checkArg<int64>(L, 2);
|
|
|
|
const char* camera_slot = LuaWrapper::checkArg<const char*>(L, 4);
|
2015-09-02 11:14:42 +02:00
|
|
|
|
|
|
|
FrameBuffer* fbs[16];
|
|
|
|
int len = Math::minValue((int)lua_rawlen(L, 3), lengthOf(fbs));
|
|
|
|
for (int i = 0; i < len; ++i)
|
|
|
|
{
|
|
|
|
if (lua_rawgeti(L, 3, 1 + i) == LUA_TSTRING)
|
|
|
|
{
|
|
|
|
const char* fb_name = lua_tostring(L, -1);
|
|
|
|
fbs[i] = pipeline->getFramebuffer(fb_name);
|
|
|
|
}
|
|
|
|
lua_pop(L, 1);
|
|
|
|
}
|
|
|
|
|
|
|
|
RenderScene* scene = pipeline->m_scene;
|
2016-01-25 14:07:12 +01:00
|
|
|
ComponentIndex camera = scene->getCameraInSlot(camera_slot);
|
2015-09-02 11:14:42 +02:00
|
|
|
pipeline->renderLocalLightShadowmaps(camera, fbs, len, layer_mask);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-07-23 23:17:51 +02:00
|
|
|
void print(int x, int y, const char* text)
|
|
|
|
{
|
|
|
|
bgfx::dbgTextPrintf(x, y, 0x4f, text);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace LuaAPI
|
|
|
|
|
|
|
|
|
|
|
|
void PipelineImpl::registerCFunctions()
|
|
|
|
{
|
2015-10-05 22:44:03 +02:00
|
|
|
#define REGISTER_FUNCTION(name) \
|
2016-01-15 00:05:53 +01:00
|
|
|
do {\
|
|
|
|
auto f = &LuaWrapper::wrapMethod<PipelineImpl, decltype(&PipelineImpl::name), &PipelineImpl::name>; \
|
|
|
|
registerCFunction(#name, f); \
|
|
|
|
} while(false) \
|
2015-10-05 22:44:03 +02:00
|
|
|
|
|
|
|
REGISTER_FUNCTION(drawQuad);
|
2016-01-15 00:05:53 +01:00
|
|
|
REGISTER_FUNCTION(setPass);
|
|
|
|
REGISTER_FUNCTION(beginNewView);
|
|
|
|
REGISTER_FUNCTION(bindFramebufferTexture);
|
|
|
|
REGISTER_FUNCTION(applyCamera);
|
|
|
|
|
2015-10-05 22:44:03 +02:00
|
|
|
REGISTER_FUNCTION(disableBlending);
|
|
|
|
REGISTER_FUNCTION(enableAlphaWrite);
|
|
|
|
REGISTER_FUNCTION(disableAlphaWrite);
|
|
|
|
REGISTER_FUNCTION(enableRGBWrite);
|
|
|
|
REGISTER_FUNCTION(disableRGBWrite);
|
|
|
|
REGISTER_FUNCTION(enableDepthWrite);
|
|
|
|
REGISTER_FUNCTION(disableDepthWrite);
|
2016-01-15 00:05:53 +01:00
|
|
|
REGISTER_FUNCTION(renderDebugShapes);
|
|
|
|
REGISTER_FUNCTION(setFramebuffer);
|
|
|
|
REGISTER_FUNCTION(renderParticles);
|
|
|
|
REGISTER_FUNCTION(loadMaterial);
|
|
|
|
REGISTER_FUNCTION(executeCustomCommand);
|
|
|
|
REGISTER_FUNCTION(getFPS);
|
|
|
|
REGISTER_FUNCTION(createUniform);
|
2016-01-30 10:06:58 +01:00
|
|
|
REGISTER_FUNCTION(createVec4ArrayUniform);
|
2016-01-15 00:05:53 +01:00
|
|
|
REGISTER_FUNCTION(hasScene);
|
|
|
|
REGISTER_FUNCTION(cameraExists);
|
|
|
|
REGISTER_FUNCTION(enableBlending);
|
2015-10-05 22:44:03 +02:00
|
|
|
REGISTER_FUNCTION(clear);
|
|
|
|
REGISTER_FUNCTION(renderModels);
|
|
|
|
REGISTER_FUNCTION(renderShadowmap);
|
2016-01-24 17:20:03 +01:00
|
|
|
REGISTER_FUNCTION(copyRenderbuffer);
|
2016-02-08 23:23:07 +01:00
|
|
|
REGISTER_FUNCTION(setActiveDirectionalLightUniforms);
|
2016-02-10 00:00:21 +01:00
|
|
|
REGISTER_FUNCTION(setStencil);
|
|
|
|
REGISTER_FUNCTION(clearStencil);
|
|
|
|
REGISTER_FUNCTION(setStencilRMask);
|
|
|
|
REGISTER_FUNCTION(setStencilRef);
|
2016-01-15 00:05:53 +01:00
|
|
|
|
|
|
|
#undef REGISTER_FUNCTION
|
|
|
|
|
|
|
|
#define REGISTER_FUNCTION(name) \
|
|
|
|
registerCFunction(#name, LuaWrapper::wrap<decltype(&LuaAPI::name), LuaAPI::name>)
|
|
|
|
|
2016-01-24 17:20:03 +01:00
|
|
|
REGISTER_FUNCTION(deferredLocalLightLoop);
|
2016-01-15 00:05:53 +01:00
|
|
|
REGISTER_FUNCTION(print);
|
|
|
|
REGISTER_FUNCTION(logError);
|
2015-10-05 22:44:03 +02:00
|
|
|
REGISTER_FUNCTION(renderLocalLightsShadowmaps);
|
2016-01-30 10:06:58 +01:00
|
|
|
REGISTER_FUNCTION(setUniform);
|
2015-10-05 22:44:03 +02:00
|
|
|
|
|
|
|
#undef REGISTER_FUNCTION
|
2016-02-10 00:00:21 +01:00
|
|
|
|
|
|
|
#define REGISTER_STENCIL_CONST(a) \
|
|
|
|
registerConst("STENCIL_" #a, BGFX_STENCIL_##a)
|
|
|
|
|
|
|
|
REGISTER_STENCIL_CONST(TEST_LESS);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_LEQUAL);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_EQUAL);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_GEQUAL);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_GREATER);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_NOTEQUAL);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_NEVER);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_ALWAYS);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_SHIFT);
|
|
|
|
REGISTER_STENCIL_CONST(TEST_MASK);
|
|
|
|
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_ZERO);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_KEEP);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_REPLACE);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_INCR);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_INCRSAT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_DECR);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_DECRSAT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_INVERT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_SHIFT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_S_MASK);
|
|
|
|
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_ZERO);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_KEEP);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_REPLACE);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_INCR);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_INCRSAT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_DECR);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_DECRSAT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_INVERT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_SHIFT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_FAIL_Z_MASK);
|
|
|
|
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_ZERO);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_KEEP);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_REPLACE);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_INCR);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_INCRSAT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_DECR);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_DECRSAT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_INVERT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_SHIFT);
|
|
|
|
REGISTER_STENCIL_CONST(OP_PASS_Z_MASK);
|
|
|
|
|
|
|
|
registerConst("CLEAR_DEPTH", BGFX_CLEAR_DEPTH);
|
|
|
|
registerConst("CLEAR_COLOR", BGFX_CLEAR_COLOR);
|
|
|
|
registerConst("CLEAR_STENCIL", BGFX_CLEAR_STENCIL);
|
|
|
|
registerConst("CLEAR_ALL", BGFX_CLEAR_STENCIL | BGFX_CLEAR_DEPTH | BGFX_CLEAR_COLOR);
|
|
|
|
|
|
|
|
#undef REGISTER_STENCIL_CONST
|
|
|
|
|
2016-01-12 19:37:00 +01:00
|
|
|
for(auto& handler : m_custom_commands_handlers)
|
|
|
|
{
|
|
|
|
exposeCustomCommandToLua(handler);
|
|
|
|
}
|
2015-07-23 23:17:51 +02:00
|
|
|
}
|
2015-05-23 14:55:57 +02:00
|
|
|
|
|
|
|
|
2014-06-16 21:18:15 +02:00
|
|
|
} // ~namespace Lumix
|