mirror of
https://github.com/open-goal/jak-project
synced 2026-08-05 01:30:22 -04:00
single sided tris working
This commit is contained in:
@@ -590,15 +590,17 @@ void MercModelGroup::serialize(Serializer& ser) {
|
||||
void ShadowModel::serialize(Serializer& ser) {
|
||||
ser.from_str(&name);
|
||||
ser.from_ptr(&max_bones);
|
||||
ser.from_ptr(&single_tris);
|
||||
ser.from_ptr(&double_tris);
|
||||
ser.from_ptr(&single_edges);
|
||||
ser.from_ptr(&double_edges);
|
||||
ser.from_ptr(&first_vertex);
|
||||
ser.from_ptr(&num_one_bone_vertices);
|
||||
ser.from_ptr(&num_two_bone_vertices);
|
||||
ser.from_pod_vector(&single_tris);
|
||||
ser.from_pod_vector(&double_tris);
|
||||
ser.from_pod_vector(&single_edges);
|
||||
ser.from_pod_vector(&double_edges);
|
||||
}
|
||||
|
||||
void ShadowModelGroup::serialize(Serializer& ser) {
|
||||
ser.from_pod_vector(&vertices);
|
||||
ser.from_pod_vector(&indices);
|
||||
if (ser.is_saving()) {
|
||||
ser.save<size_t>(models.size());
|
||||
} else {
|
||||
@@ -794,7 +796,6 @@ void Hfragment::memory_usage(tfrag3::MemoryUsageTracker* tracker) const {
|
||||
|
||||
void ShadowModelGroup::memory_usage(MemoryUsageTracker* tracker) const {
|
||||
tracker->add(SHADOW_VERTS, vertices.size() * sizeof(ShadowVertex));
|
||||
tracker->add(SHADOW_INDEX, indices.size() * sizeof(u32));
|
||||
}
|
||||
|
||||
void Level::memory_usage(MemoryUsageTracker* tracker) const {
|
||||
|
||||
@@ -623,23 +623,35 @@ struct ShadowVertex {
|
||||
u8 mats[2];
|
||||
u8 flags;
|
||||
};
|
||||
static_assert(sizeof(ShadowVertex) == 20);
|
||||
|
||||
struct ShadowTri {
|
||||
u8 verts[3];
|
||||
};
|
||||
|
||||
struct ShadowEdge {
|
||||
u8 ind[2];
|
||||
u8 tri[2];
|
||||
};
|
||||
|
||||
struct ShadowModel {
|
||||
static constexpr int kMaxVertices = 254;
|
||||
static constexpr int kMaxTris = 254;
|
||||
std::string name;
|
||||
u32 max_bones;
|
||||
|
||||
struct Run {
|
||||
u32 first_index;
|
||||
u32 count;
|
||||
};
|
||||
Run single_tris, double_tris, single_edges, double_edges;
|
||||
std::vector<ShadowTri> single_tris, double_tris;
|
||||
std::vector<ShadowEdge> single_edges, double_edges;
|
||||
|
||||
u32 first_vertex;
|
||||
u32 num_one_bone_vertices;
|
||||
u32 num_two_bone_vertices;
|
||||
|
||||
void serialize(Serializer& ser);
|
||||
};
|
||||
|
||||
struct ShadowModelGroup {
|
||||
std::vector<ShadowVertex> vertices;
|
||||
std::vector<u32> indices;
|
||||
std::vector<ShadowModel> models;
|
||||
void serialize(Serializer& ser);
|
||||
void memory_usage(MemoryUsageTracker* tracker) const;
|
||||
|
||||
@@ -276,6 +276,41 @@ std::vector<tfrag3::ShadowVertex> convert_vertices(const ShadowData& data) {
|
||||
return result;
|
||||
}
|
||||
|
||||
tfrag3::ShadowTri convert_tri(const ShadowTri& tri) {
|
||||
tfrag3::ShadowTri result;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
result.verts[i] = tri.verts[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
tfrag3::ShadowEdge convert_edge(const ShadowEdge& edge) {
|
||||
tfrag3::ShadowEdge result;
|
||||
for (int i = 0; i < 2; i++) {
|
||||
result.ind[i] = edge.ind[i];
|
||||
result.tri[i] = edge.tri[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<tfrag3::ShadowTri> convert_tris(const std::vector<ShadowTri>& tris) {
|
||||
std::vector<tfrag3::ShadowTri> result;
|
||||
result.reserve(tris.size());
|
||||
for (auto& tri : tris) {
|
||||
result.push_back(convert_tri(tri));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<tfrag3::ShadowEdge> convert_edges(const std::vector<ShadowEdge>& edges) {
|
||||
std::vector<tfrag3::ShadowEdge> result;
|
||||
result.reserve(edges.size());
|
||||
for (auto& edge : edges) {
|
||||
result.push_back(convert_edge(edge));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void extract_shadow(const ObjectFileData& ag_data,
|
||||
const DecompilerTypeSystem& dts,
|
||||
tfrag3::Level& out,
|
||||
@@ -297,8 +332,22 @@ void extract_shadow(const ObjectFileData& ag_data,
|
||||
for (auto loc : geo_locations) {
|
||||
const ShadowData data = extract_shadow_data(ag_data.linked_data, dts, loc);
|
||||
|
||||
auto& model = sd.models.emplace_back();
|
||||
model.name = data.name;
|
||||
model.max_bones = data.num_joints;
|
||||
model.single_tris = convert_tris(data.single_tris);
|
||||
model.double_tris = convert_tris(data.double_tris);
|
||||
model.single_edges = convert_edges(data.single_edges);
|
||||
model.double_edges = convert_edges(data.double_edges);
|
||||
|
||||
const u32 vertex_offset = sd.vertices.size();
|
||||
const u32 num_vertices = data.one_bone_vertices.size() + data.two_bone_vertices.size();
|
||||
|
||||
model.first_vertex = vertex_offset;
|
||||
model.num_one_bone_vertices = data.one_bone_vertices.size();
|
||||
model.num_two_bone_vertices = data.two_bone_vertices.size();
|
||||
ASSERT(model.num_one_bone_vertices + model.num_two_bone_vertices <=
|
||||
tfrag3::ShadowModel::kMaxVertices);
|
||||
ASSERT(model.single_tris.size() + model.double_tris.size() <= tfrag3::ShadowModel::kMaxTris);
|
||||
|
||||
// insert top vertices
|
||||
auto vertices = convert_vertices(data);
|
||||
@@ -310,53 +359,6 @@ void extract_shadow(const ObjectFileData& ag_data,
|
||||
}
|
||||
sd.vertices.insert(sd.vertices.end(), vertices.begin(), vertices.end());
|
||||
|
||||
auto& model = sd.models.emplace_back();
|
||||
model.name = data.name;
|
||||
model.max_bones = data.num_joints;
|
||||
|
||||
// single triangles
|
||||
model.single_tris.first_index = sd.indices.size();
|
||||
for (auto& stri : data.single_tris) {
|
||||
sd.indices.push_back(static_cast<u32>(stri.verts[0]) + vertex_offset);
|
||||
sd.indices.push_back(static_cast<u32>(stri.verts[1]) + vertex_offset);
|
||||
sd.indices.push_back(static_cast<u32>(stri.verts[2]) + vertex_offset);
|
||||
}
|
||||
model.single_tris.count = sd.indices.size() - model.single_tris.first_index;
|
||||
|
||||
// double triangles
|
||||
model.double_tris.first_index = sd.indices.size();
|
||||
for (auto& dtri : data.double_tris) {
|
||||
sd.indices.push_back(static_cast<u32>(dtri.verts[0]) + vertex_offset + num_vertices);
|
||||
sd.indices.push_back(static_cast<u32>(dtri.verts[1]) + vertex_offset + num_vertices);
|
||||
sd.indices.push_back(static_cast<u32>(dtri.verts[2]) + vertex_offset + num_vertices);
|
||||
}
|
||||
model.double_tris.count = sd.indices.size() - model.double_tris.first_index;
|
||||
|
||||
// single edges
|
||||
model.single_edges.first_index = sd.indices.size();
|
||||
for (auto& se : data.single_edges) {
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[0]) + vertex_offset + num_vertices);
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[0]) + vertex_offset);
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[1]) + vertex_offset + num_vertices);
|
||||
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[1]) + vertex_offset + num_vertices);
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[0]) + vertex_offset);
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[1]) + vertex_offset);
|
||||
}
|
||||
model.single_edges.count = sd.indices.size() - model.single_edges.first_index;
|
||||
|
||||
model.double_edges.first_index = sd.indices.size();
|
||||
for (auto& se : data.double_edges) {
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[0]) + vertex_offset + num_vertices);
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[0]) + vertex_offset);
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[1]) + vertex_offset + num_vertices);
|
||||
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[1]) + vertex_offset + num_vertices);
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[0]) + vertex_offset);
|
||||
sd.indices.push_back(static_cast<u32>(se.ind[1]) + vertex_offset);
|
||||
}
|
||||
model.double_edges.count = sd.indices.size() - model.double_edges.first_index;
|
||||
|
||||
if (dump_level) {
|
||||
auto file_path = file_util::get_file_path(
|
||||
{"debug_out/shadow", fmt::format("{}_{}.ply", ag_data.name_in_dgo, i)});
|
||||
|
||||
@@ -56,6 +56,7 @@ set(RUNTIME_SOURCE
|
||||
graphics/opengl_renderer/foreground/Merc2BucketRenderer.cpp
|
||||
graphics/opengl_renderer/foreground/Shadow2.cpp
|
||||
graphics/opengl_renderer/foreground/Shadow3.cpp
|
||||
graphics/opengl_renderer/foreground/Shadow3CPU.cpp
|
||||
graphics/opengl_renderer/loader/Loader.cpp
|
||||
graphics/opengl_renderer/loader/LoaderStages.cpp
|
||||
graphics/opengl_renderer/ocean/CommonOceanRenderer.cpp
|
||||
|
||||
@@ -6,6 +6,9 @@ Shadow3::Shadow3(ShaderLibrary& shaders) {
|
||||
glGenVertexArrays(1, &m_opengl.vao);
|
||||
glBindVertexArray(m_opengl.vao);
|
||||
|
||||
glGenBuffers(1, &m_opengl.indices);
|
||||
glGenBuffers(1, &m_opengl.debug_verts);
|
||||
|
||||
glGenBuffers(1, &m_opengl.bones_buffer);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, m_opengl.bones_buffer);
|
||||
|
||||
@@ -43,13 +46,14 @@ Shadow3::Shadow3(ShaderLibrary& shaders) {
|
||||
|
||||
Shadow3::~Shadow3() {
|
||||
glDeleteBuffers(1, &m_opengl.bones_buffer);
|
||||
glDeleteBuffers(1, &m_opengl.indices);
|
||||
glDeleteBuffers(1, &m_opengl.debug_verts);
|
||||
glDeleteVertexArrays(1, &m_opengl.vao);
|
||||
}
|
||||
|
||||
void Shadow3::setup_for_level(SharedRenderState* render_state, const LevelData* level_data) {
|
||||
glBindVertexArray(m_opengl.vao);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, level_data->shadow_vertices);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, level_data->shadow_indices);
|
||||
glEnableVertexAttribArray(0);
|
||||
glEnableVertexAttribArray(1);
|
||||
glEnableVertexAttribArray(2);
|
||||
@@ -95,11 +99,25 @@ void set_uniform(GLuint uniform, const math::Vector3f& val) {
|
||||
void set_uniform(GLuint uniform, const math::Vector4f& val) {
|
||||
glUniform4f(uniform, val.x(), val.y(), val.z(), val.w());
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void Shadow3::draw_model(SharedRenderState* render_state,
|
||||
ShadowRequest* request,
|
||||
ScopedProfilerNode& prof) {
|
||||
ShadowCPUInput input{
|
||||
.origin = request->origin,
|
||||
.top_plane = request->top_plane,
|
||||
.bottom_plane = request->bottom_plane,
|
||||
.light_dir = request->light_dir,
|
||||
.bones = request->bones,
|
||||
.model = request->model.model,
|
||||
.vertices = &request->model.level->level->shadow_data.vertices,
|
||||
.flags = request->flags,
|
||||
.debug_highlight_tri = m_debug_tri,
|
||||
};
|
||||
calc_shadow_indices(input, &m_cpu_workspace, &m_cpu_output);
|
||||
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_opengl.bones_buffer,
|
||||
sizeof(math::Vector4f) * request->bone_idx, 128 * 16 * 4);
|
||||
const auto* geo = request->model.model;
|
||||
@@ -108,53 +126,118 @@ void Shadow3::draw_model(SharedRenderState* render_state,
|
||||
set_uniform(m_uniforms.top_plane, request->top_plane);
|
||||
set_uniform(m_uniforms.bottom_plane, request->bottom_plane);
|
||||
|
||||
// enable stencil!
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilMask(0xFF);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
// glDepthMask(GL_FALSE); // no depth writes.
|
||||
// glDrawElements(GL_TRIANGLES, m_cpu_output.num_indices, GL_UNSIGNED_INT, nullptr);
|
||||
if (m_hacks) {
|
||||
auto* model = request->model.model;
|
||||
int num_verts = model->num_one_bone_vertices + model->num_two_bone_vertices;
|
||||
std::vector<tfrag3::ShadowVertex> verts;
|
||||
for (size_t i = 0; i < num_verts; ++i) {
|
||||
auto& out = verts.emplace_back();
|
||||
out.flags = 255;
|
||||
out.mats[0] = 255;
|
||||
out.mats[1] = 255;
|
||||
out.pos[0] = m_cpu_workspace.vertices[i].x();
|
||||
out.pos[1] = m_cpu_workspace.vertices[i].y();
|
||||
out.pos[2] = m_cpu_workspace.vertices[i].z();
|
||||
out.weight = m_cpu_workspace.vertices[i].w();
|
||||
}
|
||||
|
||||
auto do_draw = [&](const tfrag3::ShadowModel::Run& run, const math::Vector3f& color) {
|
||||
set_uniform(m_uniforms.debug_color, color);
|
||||
glDrawElements(GL_TRIANGLES, run.count, GL_UNSIGNED_INT,
|
||||
(void*)(sizeof(u32) * run.first_index));
|
||||
for (size_t i = 0; i < num_verts; ++i) {
|
||||
auto& out = verts.emplace_back();
|
||||
out.flags = 255;
|
||||
out.mats[0] = 255;
|
||||
out.mats[1] = 255;
|
||||
out.pos[0] = m_cpu_workspace.dual_vertices[i].x();
|
||||
out.pos[1] = m_cpu_workspace.dual_vertices[i].y();
|
||||
out.pos[2] = m_cpu_workspace.dual_vertices[i].z();
|
||||
out.weight = m_cpu_workspace.dual_vertices[i].w();
|
||||
}
|
||||
|
||||
for (int i = 0; i < m_cpu_output.num_f0_indices; i++) {
|
||||
m_cpu_output.f0_indices[i] -= model->first_vertex;
|
||||
}
|
||||
for (int i = 0; i < m_cpu_output.num_f1_indices; i++) {
|
||||
m_cpu_output.f1_indices[i] -= model->first_vertex;
|
||||
}
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
set_uniform(m_uniforms.debug_color,color);
|
||||
// glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
// glDrawElements(GL_TRIANGLES, run.count, GL_UNSIGNED_INT,
|
||||
// (void*)(sizeof(u32) * run.first_index));
|
||||
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
};
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
glDepthMask(GL_TRUE);
|
||||
// glEnable(GL_CULL_FACE);
|
||||
// glCullFace(GL_BACK);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_opengl.debug_verts);
|
||||
glBufferData(GL_ARRAY_BUFFER, num_verts * 2 * sizeof(tfrag3::ShadowVertex), verts.data(),
|
||||
GL_DYNAMIC_DRAW);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_opengl.indices);
|
||||
set_uniform(m_uniforms.debug_color, math::Vector3f(0.5f, 0.5f, 0.5f));
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_cpu_output.num_f0_indices * sizeof(u32),
|
||||
m_cpu_output.f0_indices, GL_DYNAMIC_DRAW);
|
||||
glDrawElements(GL_TRIANGLES, m_cpu_output.num_f0_indices, GL_UNSIGNED_INT, nullptr);
|
||||
set_uniform(m_uniforms.debug_color, math::Vector3f(0.f, 0.f, 0.f));
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDrawElements(GL_TRIANGLES, m_cpu_output.num_f0_indices, GL_UNSIGNED_INT, nullptr);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
auto do_all_draws = [&]( const math::Vector3f& color) {
|
||||
glUniform1i(m_uniforms.bottom_cap, 0);
|
||||
do_draw(geo->single_tris, color);
|
||||
// do_draw(geo->double_tris, math::Vector3f(0.8, 0.5, 0.5));
|
||||
do_draw(geo->single_edges, color);
|
||||
// do_draw(geo->double_edges, math::Vector3f(0.5, 0.8, 0.5));
|
||||
// glUniform1i(m_uniforms.bottom_cap, 1);
|
||||
// do_draw(geo->single_tris, math::Vector3f(0.5, 0.5, 0.8));
|
||||
// do_draw(geo->double_tris, math::Vector3f(0.5, 0.5, 0.8));
|
||||
};
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_cpu_output.num_f1_indices * sizeof(u32),
|
||||
m_cpu_output.f1_indices, GL_DYNAMIC_DRAW);
|
||||
set_uniform(m_uniforms.debug_color, math::Vector3f(0.f, 0.f, 0.f));
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDrawElements(GL_TRIANGLES, m_cpu_output.num_f1_indices, GL_UNSIGNED_INT, nullptr);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
|
||||
// using glCullFace(GL_FRONT) seems to give us back faces.
|
||||
glEnable(GL_BLEND);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ZERO, GL_ONE);
|
||||
set_uniform(m_uniforms.debug_color, math::Vector3f(0.5f, 0.78f, 0.5f));
|
||||
glDrawElements(GL_TRIANGLES, m_cpu_output.num_f1_indices, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
glStencilFunc(GL_ALWAYS, 0, 0); // always pass stencil
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_INCR); // increment on depth pass.
|
||||
do_all_draws({0.1f, 0.1f, 0.8f});
|
||||
glCullFace(GL_FRONT);
|
||||
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); // decrement on depth pass.
|
||||
do_all_draws({0.8f, 0.1f, 0.1f});
|
||||
glDisable(GL_CULL_FACE);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, request->model.level->shadow_vertices);
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
} else {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_opengl.indices);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, m_cpu_output.num_indices * sizeof(u32),
|
||||
m_cpu_output.indices, GL_DYNAMIC_DRAW);
|
||||
// enable stencil!
|
||||
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no color writes.
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
glStencilMask(0xFF);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
glDepthMask(GL_FALSE); // no depth writes.
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_FRONT);
|
||||
glStencilFunc(GL_ALWAYS, 0, 0); // always pass stencil
|
||||
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP); // increment on depth fail
|
||||
glDrawElements(GL_TRIANGLES, m_cpu_output.num_indices, GL_UNSIGNED_INT, nullptr);
|
||||
glCullFace(GL_BACK);
|
||||
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP); // decrement on depth pass.
|
||||
glDrawElements(GL_TRIANGLES, m_cpu_output.num_indices, GL_UNSIGNED_INT, nullptr);
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
}
|
||||
|
||||
void Shadow3::finish(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
// finally, draw shadow.
|
||||
if (!m_hacks) {
|
||||
glStencilFunc(GL_NOTEQUAL, 0, 0xFF);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
|
||||
glDepthFunc(GL_ALWAYS);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFuncSeparate(GL_ONE, GL_ONE, GL_ONE, GL_ZERO);
|
||||
glColorMask(true, true, true, false);
|
||||
glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
|
||||
m_full_screen_draw.draw(math::Vector4f(0.5, 0.4, 0.3, 0.5), render_state, prof);
|
||||
}
|
||||
|
||||
// restore
|
||||
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
void Shadow3::flush_requests(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
@@ -202,7 +285,11 @@ void Shadow3::first_time_setup(SharedRenderState* render_state) {
|
||||
set_uniform(m_uniforms.hvdf_offset, render_state->camera_hvdf_off);
|
||||
}
|
||||
|
||||
void Shadow3::draw_debug_window() {}
|
||||
void Shadow3::draw_debug_window() {
|
||||
ImGui::Checkbox("hacks", &m_hacks);
|
||||
ImGui::Checkbox("near_plane", &m_near_plane_hack);
|
||||
ImGui::InputInt("Tri", &m_debug_tri);
|
||||
}
|
||||
|
||||
void Shadow3::render_jak1(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
@@ -283,6 +370,8 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
// (somewhere in the model) and following the shadow direction backward.
|
||||
request.origin = game_request.settings.center +
|
||||
game_request.settings.shadow_dir * game_request.settings.dist_to_locus;
|
||||
request.bones = g_ee_main_mem + game_request.mtx;
|
||||
request.flags = game_request.settings.flags;
|
||||
|
||||
// copy bones to buffer
|
||||
constexpr int in_stride = 8 * 4 * sizeof(float);
|
||||
@@ -299,11 +388,14 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
request.top_plane = game_request.settings.top_plane;
|
||||
request.bottom_plane = game_request.settings.bot_plane;
|
||||
if (!(kAbsolutePlanes & game_request.settings.flags)) {
|
||||
printf("relative plane mode, base is %f, move by %f\n",
|
||||
-request.bottom_plane.w() / 4096.0, game_request.settings.center.y() / 4096.0);
|
||||
// printf("relative plane mode, base is %f, move by %f\n",
|
||||
// -request.bottom_plane.w() / 4096.0, game_request.settings.center.y() / 4096.0);
|
||||
// in relative planes mode, the height of the plane is adjusted to be relative to the
|
||||
// height of the center, so the planes move and down with the model
|
||||
request.top_plane.w() -= game_request.settings.center.y();
|
||||
if (m_near_plane_hack) {
|
||||
request.bottom_plane.w() = 4096;
|
||||
}
|
||||
request.bottom_plane.w() -= game_request.settings.center.y();
|
||||
}
|
||||
|
||||
@@ -312,7 +404,7 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
if (render_state->camera_pos.xyz().dot(request.bottom_plane.xyz()) +
|
||||
request.bottom_plane.w() <
|
||||
0) {
|
||||
printf(" SKIP: camera below lower clipping plane.\n");
|
||||
// printf(" SKIP: camera below lower clipping plane.\n");
|
||||
m_next_request--;
|
||||
continue;
|
||||
}
|
||||
@@ -321,15 +413,15 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
// detect if the origin is below the clipping plane and if so, move it up.
|
||||
const float dot = request.bottom_plane.xyz().dot(request.origin);
|
||||
if (dot + request.bottom_plane.w() > 0) {
|
||||
printf(" the origin is below the clipping plane, moving it up.\n");
|
||||
printf(" center was %s\n", game_request.settings.center.to_string_aligned().c_str());
|
||||
printf(" dir was %s\n", game_request.settings.shadow_dir.to_string_aligned().c_str());
|
||||
printf(" locus %f\n", game_request.settings.dist_to_locus);
|
||||
printf(" bottom plane was %s\n",
|
||||
game_request.settings.bot_plane.to_string_aligned().c_str());
|
||||
printf(" adjusted bottom plane was %s\n",
|
||||
request.bottom_plane.to_string_aligned().c_str());
|
||||
printf(" abs flag %d\n", game_request.settings.flags & kAbsolutePlanes);
|
||||
// printf(" the origin is below the clipping plane, moving it up.\n");
|
||||
// printf(" center was %s\n", game_request.settings.center.to_string_aligned().c_str());
|
||||
// printf(" dir was %s\n", game_request.settings.shadow_dir.to_string_aligned().c_str());
|
||||
// printf(" locus %f\n", game_request.settings.dist_to_locus);
|
||||
// printf(" bottom plane was %s\n",
|
||||
// game_request.settings.bot_plane.to_string_aligned().c_str());
|
||||
// printf(" adjusted bottom plane was %s\n",
|
||||
// request.bottom_plane.to_string_aligned().c_str());
|
||||
// printf(" abs flag %d\n", game_request.settings.flags & kAbsolutePlanes);
|
||||
|
||||
request.bottom_plane.w() = -dot;
|
||||
}
|
||||
@@ -353,20 +445,20 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
return math::Vector4f(xyz.x(), xyz.y(), xyz.z(), in.w() - xyz.dot(cam_rot[3].xyz()));
|
||||
};
|
||||
|
||||
printf("plane offset before: %f\n",
|
||||
game_request.settings.center.dot(request.bottom_plane.xyz()) +
|
||||
request.bottom_plane.w());
|
||||
// printf("plane offset before: %f\n",
|
||||
// game_request.settings.center.dot(request.bottom_plane.xyz()) +
|
||||
// request.bottom_plane.w());
|
||||
|
||||
request.light_dir = rotate(request.light_dir);
|
||||
request.top_plane = rotate_plane(request.top_plane);
|
||||
request.bottom_plane = rotate_plane(request.bottom_plane);
|
||||
request.origin = transform(request.origin);
|
||||
|
||||
printf("plane offset after: %f\n",
|
||||
transform(game_request.settings.center).dot(request.bottom_plane.xyz()) +
|
||||
request.bottom_plane.w());
|
||||
printf("rot3: %s\n", cam_rot[3].to_string_aligned().c_str());
|
||||
printf(" 2: %s\n", cam_pos.to_string_aligned().c_str());
|
||||
// printf("plane offset after: %f\n",
|
||||
// transform(game_request.settings.center).dot(request.bottom_plane.xyz()) +
|
||||
// request.bottom_plane.w());
|
||||
// printf("rot3: %s\n", cam_rot[3].to_string_aligned().c_str());
|
||||
// printf(" 2: %s\n", cam_pos.to_string_aligned().c_str());
|
||||
|
||||
// printf(" origin: %s\n", (request.origin / 4096.f).to_string_aligned().c_str());
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
#include "game/graphics/opengl_renderer/BucketRenderer.h"
|
||||
#include "game/graphics/opengl_renderer/foreground/Shadow3CPU.h"
|
||||
#include "game/graphics/opengl_renderer/opengl_utils.h"
|
||||
|
||||
struct Jak1ShadowSettings {
|
||||
math::Vector<float, 3> center;
|
||||
@@ -38,7 +40,9 @@ class Shadow3 {
|
||||
math::Vector4f top_plane, bottom_plane;
|
||||
math::Vector3f light_dir;
|
||||
ShadowRequest* next = nullptr;
|
||||
const u8* bones = nullptr;
|
||||
u32 bone_idx = 0;
|
||||
u32 flags = 0;
|
||||
};
|
||||
|
||||
struct LevelChain {
|
||||
@@ -62,6 +66,8 @@ class Shadow3 {
|
||||
|
||||
struct {
|
||||
GLuint vao = -1;
|
||||
GLuint indices = -1;
|
||||
GLuint debug_verts = -1;
|
||||
GLuint bones_buffer = -1;
|
||||
int buffer_alignment = 0;
|
||||
} m_opengl;
|
||||
@@ -78,4 +84,12 @@ class Shadow3 {
|
||||
GLuint bottom_cap = 0;
|
||||
} m_uniforms;
|
||||
bool m_did_first_time_setup = false;
|
||||
|
||||
bool m_hacks = false;
|
||||
bool m_near_plane_hack = false;
|
||||
int m_debug_tri = 0;
|
||||
|
||||
ShadowCPUWorkspace m_cpu_workspace;
|
||||
ShadowCPUOutput m_cpu_output;
|
||||
FullScreenDraw m_full_screen_draw;
|
||||
};
|
||||
@@ -0,0 +1,230 @@
|
||||
#include "Shadow3CPU.h"
|
||||
|
||||
#include <set>
|
||||
|
||||
/*
|
||||
*- `xform-verts` transform mesh vertices into camera space (no perspective)
|
||||
- `init-vars` transform settings to camera space
|
||||
- `calc-dual-verts` project vertices to plane
|
||||
- `scissor-top` (only executed if shdf03 is set), clip vertices to top plane, if above
|
||||
- `scissor-edges`, clip vertices to near plane
|
||||
- `find-facing-single-tris`, set face bit to indicate orientation, cull backward ones
|
||||
- `find-single-edges`, find edges that, when extruded, should be drawn
|
||||
- `find-facing-double-tris`, set face bit indicate orientation. double sided tris, so no culling
|
||||
- `find-double-edges`, find edges to extrude from the double-sided tris
|
||||
- `add-verts`
|
||||
- `add-facing-single-tris`
|
||||
- `add-single-edges`
|
||||
- `add-double-tris`
|
||||
- `add-double-edges`
|
||||
*/
|
||||
|
||||
void transform_vertices(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
struct Bone {
|
||||
math::Vector4f mat[4];
|
||||
u8 pad[16 * 4];
|
||||
};
|
||||
static_assert(sizeof(Bone) == 128);
|
||||
const tfrag3::ShadowVertex* vertex_ptr = &input.vertices->operator[](input.model->first_vertex);
|
||||
math::Vector4f* out_ptr = work->vertices;
|
||||
const Bone* first_bone_ptr = (const Bone*)(3 * 8 * 4 * sizeof(float) + input.bones);
|
||||
|
||||
for (int i = 0; i < input.model->num_one_bone_vertices; i++) {
|
||||
const Bone& bone = first_bone_ptr[vertex_ptr->mats[0]];
|
||||
*out_ptr = bone.mat[3] + //
|
||||
bone.mat[0] * vertex_ptr->pos[0] + //
|
||||
bone.mat[1] * vertex_ptr->pos[1] + //
|
||||
bone.mat[2] * vertex_ptr->pos[2];
|
||||
vertex_ptr++;
|
||||
out_ptr++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < input.model->num_two_bone_vertices; i++) {
|
||||
const Bone& bone0 = first_bone_ptr[vertex_ptr->mats[0]];
|
||||
math::Vector4f p0 = bone0.mat[3] + //
|
||||
bone0.mat[0] * vertex_ptr->pos[0] + //
|
||||
bone0.mat[1] * vertex_ptr->pos[1] + //
|
||||
bone0.mat[2] * vertex_ptr->pos[2];
|
||||
p0 *= vertex_ptr->weight;
|
||||
const Bone& bone1 = first_bone_ptr[vertex_ptr->mats[1]];
|
||||
math::Vector4f p1 = bone1.mat[3] + //
|
||||
bone1.mat[0] * vertex_ptr->pos[0] + //
|
||||
bone1.mat[1] * vertex_ptr->pos[1] + //
|
||||
bone1.mat[2] * vertex_ptr->pos[2];
|
||||
p1 *= (1.f - vertex_ptr->weight);
|
||||
*out_ptr = p0 + p1;
|
||||
|
||||
out_ptr++;
|
||||
vertex_ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
void calc_dual_verts(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
int num_verts = input.model->num_one_bone_vertices + input.model->num_two_bone_vertices;
|
||||
for (int i = 0; i < num_verts; i++) {
|
||||
math::Vector4f origin(input.origin.x(), input.origin.y(), input.origin.z(), 1.f);
|
||||
math::Vector4f p = work->vertices[i];
|
||||
math::Vector4f offset = origin - p;
|
||||
math::Vector4f plane = input.bottom_plane;
|
||||
work->dual_vertices[i] = p - offset * p.dot(plane) / offset.xyz().dot(plane.xyz());
|
||||
}
|
||||
}
|
||||
|
||||
void scissor_top(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void scissor_edges(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
void find_facing_single_tris(const ShadowCPUInput& input,
|
||||
ShadowCPUWorkspace* work,
|
||||
ShadowCPUOutput* output,
|
||||
const std::vector<tfrag3::ShadowTri>& tris) {
|
||||
int edge_offset = input.model->num_one_bone_vertices + input.model->num_two_bone_vertices;
|
||||
int num_0 = 0;
|
||||
int num_1 = 0;
|
||||
for (size_t i = 0; i < tris.size(); i++) {
|
||||
const auto& tri = tris[i];
|
||||
math::Vector3f v0 = work->vertices[tri.verts[0]].xyz();
|
||||
math::Vector3f v1 = work->vertices[tri.verts[1]].xyz();
|
||||
math::Vector3f v2 = work->vertices[tri.verts[2]].xyz();
|
||||
math::Vector3f n = (v1 - v0).cross(v2 - v0);
|
||||
bool highlight = i == input.debug_highlight_tri;
|
||||
if (n.dot(input.light_dir) < 0.f) {
|
||||
num_0++;
|
||||
work->tri_flags[i] = 1;
|
||||
output->push_index(tri.verts[0], !highlight);
|
||||
output->push_index(tri.verts[1], !highlight);
|
||||
output->push_index(tri.verts[2], !highlight);
|
||||
} else {
|
||||
num_1++;
|
||||
work->tri_flags[i] = 0;
|
||||
output->push_index(static_cast<int>(tri.verts[0]) + edge_offset, !highlight);
|
||||
output->push_index(static_cast<int>(tri.verts[1]) + edge_offset, !highlight);
|
||||
output->push_index(static_cast<int>(tri.verts[2]) + edge_offset, !highlight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void find_facing_double_tris(const ShadowCPUInput& input,
|
||||
// ShadowCPUWorkspace* work,
|
||||
// ShadowCPUOutput* output,
|
||||
// const std::vector<tfrag3::ShadowTri>& tris) {
|
||||
// int edge_offset = input.model->num_one_bone_vertices + input.model->num_two_bone_vertices;
|
||||
// const int flag_offset = input.model->double_tris.size();
|
||||
// int num_0 = 0;
|
||||
// int num_1 = 0;
|
||||
// for (size_t i = 0; i < tris.size(); i++) {
|
||||
// const auto& tri = tris[i];
|
||||
// math::Vector3f v0 = work->vertices[tri.verts[0]].xyz();
|
||||
// math::Vector3f v1 = work->vertices[tri.verts[1]].xyz();
|
||||
// math::Vector3f v2 = work->vertices[tri.verts[2]].xyz();
|
||||
// math::Vector3f n = (v1 - v0).cross(v2 - v0);
|
||||
// if (n.dot(input.light_dir) < 0.f) {
|
||||
// num_0++;
|
||||
// work->tri_flags[i + flag_offset] = 1;
|
||||
//
|
||||
// } else {
|
||||
// num_1++;
|
||||
// work->tri_flags[i + flag_offset] = 0;
|
||||
// }
|
||||
//
|
||||
// output->push_index(tri.verts[0], false);
|
||||
// output->push_index(tri.verts[1], false);
|
||||
// output->push_index(tri.verts[2], false);
|
||||
// output->push_index(tri.verts[1], false);
|
||||
// output->push_index(tri.verts[0], false);
|
||||
// output->push_index(tri.verts[2], false);
|
||||
// output->push_index(static_cast<int>(tri.verts[0]) + edge_offset, false);
|
||||
// output->push_index(static_cast<int>(tri.verts[1]) + edge_offset, false);
|
||||
// output->push_index(static_cast<int>(tri.verts[2]) + edge_offset, false);
|
||||
// output->push_index(static_cast<int>(tri.verts[1]) + edge_offset, false);
|
||||
// output->push_index(static_cast<int>(tri.verts[0]) + edge_offset, false);
|
||||
// output->push_index(static_cast<int>(tri.verts[2]) + edge_offset, false);
|
||||
// }
|
||||
// }
|
||||
|
||||
void find_single_edges(const ShadowCPUInput& input,
|
||||
ShadowCPUWorkspace* work,
|
||||
ShadowCPUOutput* output) {
|
||||
int num_weird = 0;
|
||||
int num_0 = 0;
|
||||
int num_1 = 0;
|
||||
int edge_offset = input.model->num_one_bone_vertices + input.model->num_two_bone_vertices;
|
||||
for (size_t i = 0; i < input.model->single_edges.size(); i++) {
|
||||
const auto& e = input.model->single_edges[i];
|
||||
bool skip = false;
|
||||
bool out_back = false;
|
||||
|
||||
if (e.tri[1] == 255) {
|
||||
out_back = true;
|
||||
skip = work->tri_flags[e.tri[0]] == 0;
|
||||
num_weird++;
|
||||
} else {
|
||||
u8 f0 = work->tri_flags[e.tri[0]];
|
||||
u8 f1 = work->tri_flags[e.tri[1]];
|
||||
|
||||
if (f0 == f1) {
|
||||
skip = true;
|
||||
} else {
|
||||
if (f0 == 1) {
|
||||
out_back = true;
|
||||
num_0++;
|
||||
} else {
|
||||
num_1++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
if (out_back) {
|
||||
output->push_index(e.ind[0], true);
|
||||
output->push_index(static_cast<int>(e.ind[0]) + edge_offset, true);
|
||||
output->push_index(static_cast<int>(e.ind[1]) + edge_offset, true);
|
||||
|
||||
output->push_index(e.ind[0], true);
|
||||
output->push_index(static_cast<int>(e.ind[1]) + edge_offset, true);
|
||||
output->push_index(e.ind[1], true);
|
||||
} else {
|
||||
output->push_index(e.ind[0], true);
|
||||
output->push_index(static_cast<int>(e.ind[1]) + edge_offset, true);
|
||||
output->push_index(static_cast<int>(e.ind[0]) + edge_offset, true);
|
||||
|
||||
output->push_index(e.ind[0], true);
|
||||
output->push_index(e.ind[1], true);
|
||||
output->push_index(static_cast<int>(e.ind[1]) + edge_offset, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void find_facing_double_tris() {}
|
||||
|
||||
void find_double_edges() {}
|
||||
|
||||
void calc_shadow_indices(const ShadowCPUInput& input,
|
||||
ShadowCPUWorkspace* work,
|
||||
ShadowCPUOutput* output) {
|
||||
output->num_indices = 0;
|
||||
output->num_f0_indices = 0;
|
||||
output->num_f1_indices = 0;
|
||||
|
||||
// HACK
|
||||
for (auto& f : work->tri_flags) {
|
||||
f = 77;
|
||||
}
|
||||
|
||||
transform_vertices(input, work);
|
||||
calc_dual_verts(input, work);
|
||||
scissor_top(input, work);
|
||||
scissor_edges(input, work);
|
||||
find_facing_single_tris(input, work, output, input.model->single_tris);
|
||||
find_single_edges(input, work, output);
|
||||
// find_facing_double_tris(input, work, output, input.model->double_tris);
|
||||
|
||||
for (int i = 0; i < output->num_indices; i++) {
|
||||
output->indices[i] += input.model->first_vertex;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
#include "common/custom_data/Tfrag3Data.h"
|
||||
#include "common/math/Vector.h"
|
||||
|
||||
struct ShadowCPUInput {
|
||||
math::Vector3f origin;
|
||||
math::Vector4f top_plane, bottom_plane;
|
||||
math::Vector3f light_dir;
|
||||
const u8* bones = nullptr;
|
||||
const tfrag3::ShadowModel* model = nullptr;
|
||||
std::vector<tfrag3::ShadowVertex>* vertices = nullptr;
|
||||
u32 flags = 0;
|
||||
int debug_highlight_tri = 0;
|
||||
};
|
||||
|
||||
struct ShadowCPUOutput {
|
||||
static constexpr int kMaxIndices = (256 * 3) + (256 * 3 * 2);
|
||||
|
||||
void push_index(u32 i, bool facing) {
|
||||
indices[num_indices++] = i;
|
||||
if (!facing) {
|
||||
f0_indices[num_f0_indices++] = i;
|
||||
} else {
|
||||
f1_indices[num_f1_indices++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
int num_indices = 0;
|
||||
u32 indices[kMaxIndices];
|
||||
|
||||
int num_f0_indices = 0;
|
||||
u32 f0_indices[kMaxIndices];
|
||||
int num_f1_indices = 0;
|
||||
int f1_indices[kMaxIndices];
|
||||
};
|
||||
|
||||
struct ShadowCPUWorkspace {
|
||||
math::Vector4f vertices[tfrag3::ShadowModel::kMaxVertices];
|
||||
math::Vector4f dual_vertices[tfrag3::ShadowModel::kMaxVertices];
|
||||
u8 tri_flags[tfrag3::ShadowModel::kMaxTris];
|
||||
};
|
||||
|
||||
void calc_shadow_indices(const ShadowCPUInput& input,
|
||||
ShadowCPUWorkspace* work,
|
||||
ShadowCPUOutput* output);
|
||||
@@ -504,7 +504,6 @@ void Loader::update(TexturePool& texture_pool) {
|
||||
m_garbage_buffers.push_back(lev->collide_vertices);
|
||||
m_garbage_buffers.push_back(lev->merc_vertices);
|
||||
m_garbage_buffers.push_back(lev->merc_indices);
|
||||
m_garbage_buffers.push_back(lev->shadow_indices);
|
||||
m_garbage_buffers.push_back(lev->shadow_vertices);
|
||||
|
||||
for (auto& model : lev->level->merc_data.models) {
|
||||
|
||||
@@ -693,7 +693,6 @@ ShadowLoaderStage::ShadowLoaderStage() : LoaderStage("shadow") {}
|
||||
void ShadowLoaderStage::reset() {
|
||||
m_done = false;
|
||||
m_opengl = false;
|
||||
m_vtx_uploaded = false;
|
||||
m_idx = 0;
|
||||
}
|
||||
|
||||
@@ -703,12 +702,6 @@ bool ShadowLoaderStage::run(Timer& /*timer*/, LoaderInput& data) {
|
||||
}
|
||||
|
||||
if (!m_opengl) {
|
||||
glGenBuffers(1, &data.lev_data->shadow_indices);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, data.lev_data->shadow_indices);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
|
||||
data.lev_data->level->shadow_data.indices.size() * sizeof(u32), nullptr,
|
||||
GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, &data.lev_data->shadow_vertices);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, data.lev_data->shadow_vertices);
|
||||
glBufferData(GL_ARRAY_BUFFER,
|
||||
@@ -717,20 +710,6 @@ bool ShadowLoaderStage::run(Timer& /*timer*/, LoaderInput& data) {
|
||||
m_opengl = true;
|
||||
}
|
||||
|
||||
if (!m_vtx_uploaded) {
|
||||
u32 start = m_idx;
|
||||
m_idx = std::min(start + 32768, (u32)data.lev_data->level->shadow_data.indices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, data.lev_data->shadow_indices);
|
||||
glBufferSubData(GL_ARRAY_BUFFER, start * sizeof(u32), (m_idx - start) * sizeof(u32),
|
||||
data.lev_data->level->shadow_data.indices.data() + start);
|
||||
if (m_idx != data.lev_data->level->shadow_data.indices.size()) {
|
||||
return false;
|
||||
} else {
|
||||
m_idx = 0;
|
||||
m_vtx_uploaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
u32 start = m_idx;
|
||||
m_idx = std::min(start + 32768, (u32)data.lev_data->level->shadow_data.vertices.size());
|
||||
glBindBuffer(GL_ARRAY_BUFFER, data.lev_data->shadow_vertices);
|
||||
|
||||
@@ -27,6 +27,5 @@ public:
|
||||
private:
|
||||
bool m_done = false;
|
||||
bool m_opengl = false;
|
||||
bool m_vtx_uploaded = false;
|
||||
u32 m_idx = 0;
|
||||
};
|
||||
@@ -29,7 +29,6 @@ struct LevelData {
|
||||
std::unordered_map<std::string, const tfrag3::MercModel*> merc_model_lookup;
|
||||
|
||||
GLuint shadow_vertices;
|
||||
GLuint shadow_indices;
|
||||
std::unordered_map<std::string, const tfrag3::ShadowModel*> shadow_model_lookup;
|
||||
|
||||
GLuint hfrag_vertices;
|
||||
|
||||
@@ -51,6 +51,7 @@ vec4 dual(vec4 p, vec4 plane) {
|
||||
}
|
||||
|
||||
vec4 scissor(vec4 p, vec4 plane) {
|
||||
return p;
|
||||
float plane_offset = dot(p, plane);
|
||||
if (plane_offset > 0) {
|
||||
vec4 offset = vec4(origin, 1) - p;
|
||||
@@ -62,26 +63,30 @@ vec4 scissor(vec4 p, vec4 plane) {
|
||||
|
||||
void main() {
|
||||
vec4 p = vec4(position_in, 1);
|
||||
vec4 vtx_pos;
|
||||
|
||||
vec4 vtx_pos = -bones[mats[0] + offset].X * p * weight_in;
|
||||
|
||||
if (weight_in > 1) {
|
||||
vtx_pos += -bones[mats[1] + offset].X * p * (1.f - weight_in);
|
||||
}
|
||||
|
||||
|
||||
if (bottom_cap) {
|
||||
vtx_pos = dual(vtx_pos, bottom_plane);
|
||||
if (mats[0] == 255) {
|
||||
// debug hack!
|
||||
vtx_pos = vec4(position_in, weight_in);
|
||||
} else {
|
||||
if ((flags & uint(1)) != 0) {
|
||||
vtx_pos = -bones[mats[0] + offset].X * p * weight_in;
|
||||
|
||||
if (weight_in > 1) {
|
||||
vtx_pos += -bones[mats[1] + offset].X * p * (1.f - weight_in);
|
||||
}
|
||||
|
||||
|
||||
if (bottom_cap) {
|
||||
vtx_pos = dual(vtx_pos, bottom_plane);
|
||||
} else {
|
||||
vtx_pos = scissor(vtx_pos, top_plane);
|
||||
if ((flags & uint(1)) != 0) {
|
||||
vtx_pos = dual(vtx_pos, bottom_plane);
|
||||
} else {
|
||||
vtx_pos = scissor(vtx_pos, top_plane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
vec4 transformed = perspective_matrix * vtx_pos;
|
||||
|
||||
float Q = fog_constants.x / transformed[3];
|
||||
@@ -98,5 +103,5 @@ void main() {
|
||||
gl_Position = transformed;
|
||||
|
||||
|
||||
vtx_color = vec4(debug_color, 1.0);
|
||||
vtx_color = vec4(debug_color, 0.5);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user