mirror of
https://github.com/open-goal/jak-project
synced 2026-06-27 19:02:59 -04:00
lots of minor shadow fixes
This commit is contained in:
@@ -35,7 +35,6 @@ Shadow3::Shadow3(ShaderLibrary& shaders) {
|
||||
m_uniforms.origin = glGetUniformLocation(id, "origin");
|
||||
m_uniforms.top_plane = glGetUniformLocation(id, "top_plane");
|
||||
m_uniforms.bottom_plane = glGetUniformLocation(id, "bottom_plane");
|
||||
m_uniforms.bottom_cap = glGetUniformLocation(id, "bottom_cap");
|
||||
}
|
||||
|
||||
std::vector<u8> temp(MAX_SHADER_BONE_VECTORS * sizeof(math::Vector4f));
|
||||
@@ -117,10 +116,11 @@ void Shadow3::draw_model(SharedRenderState* render_state,
|
||||
.debug_highlight_tri = m_debug_tri,
|
||||
};
|
||||
calc_shadow_indices(input, &m_cpu_workspace, &m_cpu_output);
|
||||
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, m_opengl.bones_buffer);
|
||||
glBindBufferRange(GL_UNIFORM_BUFFER, 1, m_opengl.bones_buffer,
|
||||
sizeof(math::Vector4f) * request->bone_idx, 128 * 16 * 4);
|
||||
const auto* geo = request->model.model;
|
||||
// printf("draw %s\n", geo->name.c_str());
|
||||
|
||||
set_uniform(m_uniforms.origin, request->origin);
|
||||
set_uniform(m_uniforms.top_plane, request->top_plane);
|
||||
@@ -153,18 +153,12 @@ void Shadow3::draw_model(SharedRenderState* render_state,
|
||||
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);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
glDepthMask(GL_TRUE);
|
||||
// glEnable(GL_CULL_FACE);
|
||||
// glCullFace(GL_BACK);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(m_cull_back ? GL_BACK : GL_FRONT);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, m_opengl.debug_verts);
|
||||
glBufferData(GL_ARRAY_BUFFER, num_verts * 2 * sizeof(tfrag3::ShadowVertex), verts.data(),
|
||||
GL_DYNAMIC_DRAW);
|
||||
@@ -207,15 +201,28 @@ void Shadow3::draw_model(SharedRenderState* render_state,
|
||||
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);
|
||||
if (false) {
|
||||
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 fail
|
||||
glDrawElements(GL_TRIANGLES, m_cpu_output.num_indices, GL_UNSIGNED_INT, nullptr);
|
||||
glCullFace(GL_FRONT);
|
||||
glStencilFunc(GL_ALWAYS, 0, 0);
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_DECR); // decrement on depth pass.
|
||||
glDrawElements(GL_TRIANGLES, m_cpu_output.num_indices, GL_UNSIGNED_INT, nullptr);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -238,6 +245,11 @@ void Shadow3::finish(SharedRenderState* render_state, ScopedProfilerNode& prof)
|
||||
glBlendEquation(GL_FUNC_ADD);
|
||||
glDepthMask(GL_TRUE);
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
glBindVertexArray(0);
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
glBindBuffer(GL_UNIFORM_BUFFER, 0);
|
||||
}
|
||||
|
||||
void Shadow3::flush_requests(SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||
@@ -258,6 +270,7 @@ void Shadow3::flush_requests(SharedRenderState* render_state, ScopedProfilerNode
|
||||
for (auto& c : m_level_chains) {
|
||||
if (!c.head)
|
||||
continue;
|
||||
// printf("in level %s\n", c.level->level->level_name.c_str());
|
||||
setup_for_level(render_state, c.level);
|
||||
ShadowRequest* iter = c.head;
|
||||
while (iter) {
|
||||
@@ -288,21 +301,19 @@ void Shadow3::first_time_setup(SharedRenderState* render_state) {
|
||||
void Shadow3::draw_debug_window() {
|
||||
ImGui::Checkbox("hacks", &m_hacks);
|
||||
ImGui::Checkbox("near_plane", &m_near_plane_hack);
|
||||
ImGui::Checkbox("back?", &m_cull_back);
|
||||
ImGui::InputInt("Tri", &m_debug_tri);
|
||||
}
|
||||
|
||||
void Shadow3::render_jak1(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
ScopedProfilerNode& prof) {
|
||||
printf("Jak1 shadow render\n");
|
||||
m_did_first_time_setup = false;
|
||||
|
||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||
auto dmatag = dma.current_tag();
|
||||
// auto dmatag = dma.current_tag();
|
||||
auto data = dma.read_and_advance();
|
||||
int run_idx = 0;
|
||||
if (data.vifcode0().kind == VifCode::Kind::PC_PORT) {
|
||||
printf(" Run %d start\n", run_idx);
|
||||
u32 next = data.data_offset;
|
||||
while (next) {
|
||||
Jak1ShadowRequest game_request;
|
||||
@@ -312,7 +323,7 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
char name[128];
|
||||
strncpy(name, (const char*)(g_ee_main_mem) + 4 + game_request.geo_name, 128);
|
||||
name[127] = 0;
|
||||
printf(" draw %s\n", name);
|
||||
// printf(" draw %s\n", name);
|
||||
|
||||
auto model = render_state->loader->get_shadow_model(name);
|
||||
if (!model) {
|
||||
@@ -362,8 +373,6 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
|
||||
// grab the next request and link it to the chain for the level.
|
||||
auto& request = m_requests[m_next_request++];
|
||||
request.next = chain->head;
|
||||
chain->head = &request;
|
||||
|
||||
request.model = *model;
|
||||
// the origin of "light" for the shadow is found by starting at the "center" point
|
||||
@@ -400,7 +409,7 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
}
|
||||
|
||||
// skip drawing if the camera is below the lower clipping plane
|
||||
if (kCullWhenUnderPlane & game_request.settings.flags) {
|
||||
if (!m_hacks && (kCullWhenUnderPlane & game_request.settings.flags)) {
|
||||
if (render_state->camera_pos.xyz().dot(request.bottom_plane.xyz()) +
|
||||
request.bottom_plane.w() <
|
||||
0) {
|
||||
@@ -410,14 +419,17 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
}
|
||||
}
|
||||
|
||||
request.next = chain->head;
|
||||
chain->head = &request;
|
||||
|
||||
// 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",
|
||||
// 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());
|
||||
@@ -454,6 +466,10 @@ void Shadow3::render_jak1(DmaFollower& dma,
|
||||
request.bottom_plane = rotate_plane(request.bottom_plane);
|
||||
request.origin = transform(request.origin);
|
||||
|
||||
math::Vector3f up_rt_w = math::Vector3f(0, 1, 0);
|
||||
math::Vector3f up_rt_cam = rotate(up_rt_w);
|
||||
// printf("ups: %f\n", up_rt_cam.dot(request.bottom_plane.xyz()));
|
||||
|
||||
// printf("plane offset after: %f\n",
|
||||
// transform(game_request.settings.center).dot(request.bottom_plane.xyz()) +
|
||||
// request.bottom_plane.w());
|
||||
|
||||
@@ -81,11 +81,11 @@ class Shadow3 {
|
||||
GLuint bottom_plane = 0;
|
||||
GLuint top_plane = 0;
|
||||
GLuint origin = 0;
|
||||
GLuint bottom_cap = 0;
|
||||
} m_uniforms;
|
||||
bool m_did_first_time_setup = false;
|
||||
|
||||
bool m_hacks = false;
|
||||
bool m_cull_back = false;
|
||||
bool m_near_plane_hack = false;
|
||||
int m_debug_tri = 0;
|
||||
|
||||
|
||||
@@ -1,24 +1,18 @@
|
||||
#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`
|
||||
*/
|
||||
// This file generates indices with correct face orientations for a shadow volume.
|
||||
// As usual, Naughty Dog has a few tricks.
|
||||
// You can have double-sided triangles - basically infinitely thin geometry that casts a shadow.
|
||||
// It is also okay to have holes in your mesh of single-sided triangles as long as no light ray
|
||||
// would enter or exit your "volume" through the gap first or last.
|
||||
// (so you should only have gaps for weird internal areas that would never have an effect on the
|
||||
// final shadow) It is always safe to eliminate triangles that are fully enclosed within another
|
||||
// closed volume.
|
||||
|
||||
/**
|
||||
* Since the shadow mesh has skeletal animation, we must compute the vertex positions on the CPU to
|
||||
* determine the shadow volume. There's no way around this other than geometry shaders.
|
||||
*/
|
||||
void transform_vertices(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
struct Bone {
|
||||
math::Vector4f mat[4];
|
||||
@@ -29,6 +23,7 @@ void transform_vertices(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
math::Vector4f* out_ptr = work->vertices;
|
||||
const Bone* first_bone_ptr = (const Bone*)(3 * 8 * 4 * sizeof(float) + input.bones);
|
||||
|
||||
// vertices influenced by one bone
|
||||
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] + //
|
||||
@@ -39,6 +34,7 @@ void transform_vertices(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
out_ptr++;
|
||||
}
|
||||
|
||||
// vertices influenced by two bones.
|
||||
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] + //
|
||||
@@ -59,6 +55,12 @@ void transform_vertices(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute the projection of each vertex onto the "bottom plane". This is another ND trick.
|
||||
* Instead of doing the traditional thing of making an infinite volume, they effectively clip
|
||||
* the mesh against some plane that sits (ideally) slightly below the ground. This avoids the issue
|
||||
* of casting shadows on the "wrong side of the ground", and reduces fill.
|
||||
*/
|
||||
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++) {
|
||||
@@ -70,140 +72,185 @@ void calc_dual_verts(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Another ND trick: clip the mesh against some plane slightly above the ground. I think this just
|
||||
* reduces fill.
|
||||
*/
|
||||
void scissor_top(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Clip against the near plane. I'm not sure why this is needed, but it may be another fill-reducing
|
||||
* trick, or maybe just allows them to avoid scissoring against the near plane in the VU program.
|
||||
*/
|
||||
void scissor_edges(const ShadowCPUInput& input, ShadowCPUWorkspace* work) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
/**
|
||||
* Add "cap" triangles. These are either triangles in the original mesh that point toward the light,
|
||||
* and their projection to the bottom plane.
|
||||
*/
|
||||
void find_facing_single_tris(const ShadowCPUInput& input,
|
||||
ShadowCPUWorkspace* work,
|
||||
ShadowCPUOutput* output,
|
||||
const std::vector<tfrag3::ShadowTri>& tris) {
|
||||
const int num_verts = input.model->num_one_bone_vertices + input.model->num_two_bone_vertices;
|
||||
for (size_t i = 0; i < tris.size(); i++) {
|
||||
const auto& tri = tris[i];
|
||||
// recompute normal after transformation:
|
||||
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) {
|
||||
work->tri_flags[i] = 1;
|
||||
// facing toward the light, add the triangle as it appears in the original mesh
|
||||
output->push_index(tri.verts[0], !highlight);
|
||||
output->push_index(tri.verts[1], !highlight);
|
||||
output->push_index(tri.verts[2], !highlight);
|
||||
// and the projection. This triangle has the normal pointing the other way, since it closes
|
||||
// the volume, so the indices are flipping.
|
||||
output->push_index(static_cast<int>(tri.verts[0]) + num_verts, !highlight);
|
||||
output->push_index(static_cast<int>(tri.verts[2]) + num_verts, !highlight);
|
||||
output->push_index(static_cast<int>(tri.verts[1]) + num_verts, !highlight);
|
||||
} else {
|
||||
// facing away from the light.
|
||||
work->tri_flags[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Build walls. A wall will happen on an edge between a facing and non-facing tri.
|
||||
* Or, if there is no second tri, there will be a wall whenever the first tri is facing.
|
||||
*/
|
||||
void find_single_edges(const ShadowCPUInput& input,
|
||||
ShadowCPUWorkspace* work,
|
||||
ShadowCPUOutput* output) {
|
||||
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 < input.model->single_edges.size(); i++) {
|
||||
const auto& e = input.model->single_edges[i];
|
||||
const u8 f0 = work->tri_flags[e.tri[0]];
|
||||
const auto t1 = e.tri[1];
|
||||
|
||||
bool flip = false; // set if the edge orientation is backward.
|
||||
if (t1 == 255) {
|
||||
if (f0 == 0) { // only one tri, skip if not facing
|
||||
continue;
|
||||
}
|
||||
// if facing, then the edge is already oriented the right way!
|
||||
} else {
|
||||
const u8 f1 = work->tri_flags[e.tri[1]];
|
||||
if (f0 == f1) { // both tris face the same way - no wall needed.
|
||||
continue;
|
||||
}
|
||||
flip = f0 == 0; // ND convention here for edge direction.
|
||||
// this is somewhat of an odd convention because it seems like edges on singles
|
||||
// are backward. oh well.
|
||||
}
|
||||
|
||||
if (!flip) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Add cap triangles for double triangles. One side is always facing!
|
||||
*/
|
||||
void find_facing_double_tris(const ShadowCPUInput& input,
|
||||
ShadowCPUWorkspace* work,
|
||||
ShadowCPUOutput* output,
|
||||
const std::vector<tfrag3::ShadowTri>& tris) {
|
||||
const int num_verts = input.model->num_one_bone_vertices + input.model->num_two_bone_vertices;
|
||||
const int flag_offset = 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);
|
||||
work->tri_flags[i + flag_offset] = 1;
|
||||
// treat this as a normal single-sided triangle that is facing.
|
||||
output->push_index(tri.verts[0], false);
|
||||
output->push_index(tri.verts[1], false);
|
||||
output->push_index(tri.verts[2], false);
|
||||
output->push_index(static_cast<int>(tri.verts[0]) + num_verts, false);
|
||||
output->push_index(static_cast<int>(tri.verts[2]) + num_verts, false);
|
||||
output->push_index(static_cast<int>(tri.verts[1]) + num_verts, false);
|
||||
} 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);
|
||||
work->tri_flags[i + flag_offset] = 0;
|
||||
// we need to flip vertices to face the light.
|
||||
output->push_index(tri.verts[0], false);
|
||||
output->push_index(tri.verts[2], false);
|
||||
output->push_index(tri.verts[1], false);
|
||||
output->push_index(static_cast<int>(tri.verts[0]) + num_verts, false);
|
||||
output->push_index(static_cast<int>(tri.verts[1]) + num_verts, false);
|
||||
output->push_index(static_cast<int>(tri.verts[2]) + num_verts, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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,
|
||||
void find_double_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;
|
||||
for (size_t i = 0; i < input.model->double_edges.size(); i++) {
|
||||
const auto& e = input.model->double_edges[i];
|
||||
const u8 f0 = work->tri_flags[e.tri[0]];
|
||||
const auto t1 = e.tri[1];
|
||||
|
||||
if (e.tri[1] == 255) {
|
||||
out_back = true;
|
||||
skip = work->tri_flags[e.tri[0]] == 0;
|
||||
num_weird++;
|
||||
auto add = [&](bool flip) {
|
||||
if (flip) {
|
||||
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);
|
||||
}
|
||||
};
|
||||
|
||||
if (t1 == 255) {
|
||||
add(f0 == 1);
|
||||
} 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);
|
||||
}
|
||||
const u8 f1 = work->tri_flags[e.tri[1]];
|
||||
ASSERT(f0 != 77);
|
||||
ASSERT(f1 != 77);
|
||||
add(f0 == 1);
|
||||
add(f1 != 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void find_facing_double_tris() {}
|
||||
|
||||
void find_double_edges() {}
|
||||
|
||||
void calc_shadow_indices(const ShadowCPUInput& input,
|
||||
ShadowCPUWorkspace* work,
|
||||
ShadowCPUOutput* output) {
|
||||
@@ -222,7 +269,8 @@ void calc_shadow_indices(const ShadowCPUInput& input,
|
||||
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);
|
||||
find_facing_double_tris(input, work, output, input.model->double_tris);
|
||||
find_double_edges(input, work, output);
|
||||
|
||||
for (int i = 0; i < output->num_indices; i++) {
|
||||
output->indices[i] += input.model->first_vertex;
|
||||
|
||||
@@ -14,7 +14,7 @@ struct ShadowCPUInput {
|
||||
};
|
||||
|
||||
struct ShadowCPUOutput {
|
||||
static constexpr int kMaxIndices = (256 * 3) + (256 * 3 * 2);
|
||||
static constexpr int kMaxIndices = (256 * 3 * 2) + (256 * 3 * 2);
|
||||
|
||||
void push_index(u32 i, bool facing) {
|
||||
indices[num_indices++] = i;
|
||||
|
||||
@@ -15,13 +15,10 @@ uniform vec3 debug_color;
|
||||
uniform vec4 bottom_plane;
|
||||
uniform vec4 top_plane;
|
||||
uniform vec3 origin;
|
||||
uniform bool bottom_cap;
|
||||
|
||||
// output
|
||||
out vec4 vtx_color;
|
||||
|
||||
int offset = 0;
|
||||
|
||||
struct MercMatrixData {
|
||||
mat4 X;
|
||||
};
|
||||
@@ -62,6 +59,7 @@ vec4 scissor(vec4 p, vec4 plane) {
|
||||
}
|
||||
|
||||
void main() {
|
||||
float w_debug = 7;
|
||||
vec4 p = vec4(position_in, 1);
|
||||
vec4 vtx_pos;
|
||||
|
||||
@@ -69,25 +67,23 @@ void main() {
|
||||
// debug hack!
|
||||
vtx_pos = vec4(position_in, weight_in);
|
||||
} else {
|
||||
vtx_pos = -bones[mats[0] + offset].X * p * weight_in;
|
||||
vtx_pos = bones[mats[0]].X * p * weight_in;
|
||||
|
||||
if (weight_in > 1) {
|
||||
vtx_pos += -bones[mats[1] + offset].X * p * (1.f - weight_in);
|
||||
if (weight_in < 1) {
|
||||
vtx_pos += bones[mats[1]].X * p * (1.f - weight_in);
|
||||
}
|
||||
|
||||
|
||||
if (bottom_cap) {
|
||||
w_debug = vtx_pos.w;
|
||||
if ((flags & uint(1)) != 0) {
|
||||
vtx_pos = dual(vtx_pos, bottom_plane);
|
||||
} else {
|
||||
if ((flags & uint(1)) != 0) {
|
||||
vtx_pos = dual(vtx_pos, bottom_plane);
|
||||
} else {
|
||||
vtx_pos = scissor(vtx_pos, top_plane);
|
||||
}
|
||||
vtx_pos = scissor(vtx_pos, top_plane);
|
||||
}
|
||||
}
|
||||
|
||||
vec4 transformed = perspective_matrix * vtx_pos;
|
||||
|
||||
|
||||
vec4 transformed = perspective_matrix * -vtx_pos;
|
||||
|
||||
float Q = fog_constants.x / transformed[3];
|
||||
|
||||
@@ -103,5 +99,5 @@ void main() {
|
||||
gl_Position = transformed;
|
||||
|
||||
|
||||
vtx_color = vec4(debug_color, 0.5);
|
||||
vtx_color = vec4(debug_color, w_debug);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user