mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
[jak2] misc fixes to renderers (#2488)
Fixes decal on tfrag: ![image](https://user-images.githubusercontent.com/48171810/232174352-11153941-e1f9-4472-becb-f266c2a309e5.png) Sets up jak 2 alpha shrub test settings. They are still too dark, but there's no longer incorrect alpha test: ![image](https://user-images.githubusercontent.com/48171810/232174590-f9caa6c5-f190-4c78-b720-5f4055490d47.png) Fix decal on shrub, a feature used in exactly one place in jak 1: ![image](https://user-images.githubusercontent.com/48171810/232174614-8ea65ca5-a183-45f7-ae79-6bf06a937007.png) Fixed issue with u16 overflow in castle on the alpha channel, causing flickering. It barely overflowed, which made me suspicious that we had some error somewhere. But I think that there code is robust against overflows.
This commit is contained in:
parent
ba12d804f7
commit
c7f2a23abf
|
@ -73,7 +73,7 @@ struct MemoryUsageTracker {
|
||||||
void add(MemoryUsageCategory category, u32 size_bytes) { data[category] += size_bytes; }
|
void add(MemoryUsageCategory category, u32 size_bytes) { data[category] += size_bytes; }
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr int TFRAG3_VERSION = 33;
|
constexpr int TFRAG3_VERSION = 34;
|
||||||
|
|
||||||
// These vertices should be uploaded to the GPU at load time and don't change
|
// These vertices should be uploaded to the GPU at load time and don't change
|
||||||
struct PreloadedVertex {
|
struct PreloadedVertex {
|
||||||
|
|
|
@ -197,7 +197,7 @@ std::vector<level_tools::TextureRemap> extract_bsp_from_level(const ObjectFileDB
|
||||||
dynamic_cast<level_tools::shrub_types::DrawableTreeInstanceShrub*>(draw_tree.get());
|
dynamic_cast<level_tools::shrub_types::DrawableTreeInstanceShrub*>(draw_tree.get());
|
||||||
ASSERT(as_shrub_tree);
|
ASSERT(as_shrub_tree);
|
||||||
extract_shrub(as_shrub_tree, fmt::format("{}-{}-shrub", dgo_name, i++),
|
extract_shrub(as_shrub_tree, fmt::format("{}-{}-shrub", dgo_name, i++),
|
||||||
bsp_header.texture_remap_table, tex_db, {}, level_data, false);
|
bsp_header.texture_remap_table, tex_db, {}, level_data, false, db.version());
|
||||||
} else if (draw_tree->my_type() == "drawable-tree-collide-fragment" && extract_collision) {
|
} else if (draw_tree->my_type() == "drawable-tree-collide-fragment" && extract_collision) {
|
||||||
auto as_collide_frags =
|
auto as_collide_frags =
|
||||||
dynamic_cast<level_tools::DrawableTreeCollideFragment*>(draw_tree.get());
|
dynamic_cast<level_tools::DrawableTreeCollideFragment*>(draw_tree.get());
|
||||||
|
|
|
@ -142,7 +142,8 @@ u32 remap_texture(u32 original, const std::vector<level_tools::TextureRemap>& ma
|
||||||
DrawSettings adgif_to_draw_mode(const AdGifData& ad,
|
DrawSettings adgif_to_draw_mode(const AdGifData& ad,
|
||||||
const TextureDB& tdb,
|
const TextureDB& tdb,
|
||||||
const std::vector<level_tools::TextureRemap>& map,
|
const std::vector<level_tools::TextureRemap>& map,
|
||||||
int count) {
|
int count,
|
||||||
|
bool alpha_tpage_flag) {
|
||||||
// initialize draw mode
|
// initialize draw mode
|
||||||
DrawMode current_mode;
|
DrawMode current_mode;
|
||||||
current_mode.set_at(true);
|
current_mode.set_at(true);
|
||||||
|
@ -155,13 +156,25 @@ DrawSettings adgif_to_draw_mode(const AdGifData& ad,
|
||||||
current_mode.set_alpha_blend(DrawMode::AlphaBlend::SRC_SRC_SRC_SRC);
|
current_mode.set_alpha_blend(DrawMode::AlphaBlend::SRC_SRC_SRC_SRC);
|
||||||
current_mode.enable_fog();
|
current_mode.enable_fog();
|
||||||
|
|
||||||
|
if (alpha_tpage_flag) {
|
||||||
|
current_mode.set_alpha_test(DrawMode::AlphaTest::NEVER);
|
||||||
|
current_mode.set_aref(0);
|
||||||
|
current_mode.set_alpha_fail(GsTest::AlphaFail::FB_ONLY);
|
||||||
|
}
|
||||||
|
|
||||||
// ADGIF 0
|
// ADGIF 0
|
||||||
bool weird = (u8)ad.tex0_addr != (u32)GsRegisterAddress::TEX0_1;
|
bool weird = (u8)ad.tex0_addr != (u32)GsRegisterAddress::TEX0_1;
|
||||||
if (weird) {
|
if (weird) {
|
||||||
lg::info("---------------- WEIRD: 0x{:x}", ad.tex0_addr);
|
lg::info("---------------- WEIRD: 0x{:x}", ad.tex0_addr);
|
||||||
lg::info("i have {} verts", count);
|
lg::info("i have {} verts", count);
|
||||||
} else {
|
} else {
|
||||||
ASSERT(ad.tex0_data == 0 || ad.tex0_data == 0x800000000); // note: decal?? todo
|
if (ad.tex0_data == 0) {
|
||||||
|
current_mode.set_decal(false);
|
||||||
|
} else if (ad.tex0_data == 0x8'0000'0000) {
|
||||||
|
current_mode.set_decal(true);
|
||||||
|
} else {
|
||||||
|
ASSERT(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// tw/th
|
// tw/th
|
||||||
|
@ -241,7 +254,8 @@ DrawSettings adgif_to_draw_mode(const AdGifData& ad,
|
||||||
|
|
||||||
ShrubProtoInfo extract_proto(const shrub_types::PrototypeBucketShrub& proto,
|
ShrubProtoInfo extract_proto(const shrub_types::PrototypeBucketShrub& proto,
|
||||||
const TextureDB& tdb,
|
const TextureDB& tdb,
|
||||||
const std::vector<level_tools::TextureRemap>& map) {
|
const std::vector<level_tools::TextureRemap>& map,
|
||||||
|
GameVersion version) {
|
||||||
ShrubProtoInfo result;
|
ShrubProtoInfo result;
|
||||||
for (int frag_idx = 0; frag_idx < proto.generic_geom.length; frag_idx++) {
|
for (int frag_idx = 0; frag_idx < proto.generic_geom.length; frag_idx++) {
|
||||||
auto& frag_out = result.frags.emplace_back();
|
auto& frag_out = result.frags.emplace_back();
|
||||||
|
@ -287,7 +301,11 @@ ShrubProtoInfo extract_proto(const shrub_types::PrototypeBucketShrub& proto,
|
||||||
ASSERT(3 * (vert_idx + draw.start_vtx_idx) + 3 <= frag.col.size());
|
ASSERT(3 * (vert_idx + draw.start_vtx_idx) + 3 <= frag.col.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
draw.settings = adgif_to_draw_mode(ag, tdb, map, count);
|
bool alpha_tpage_flag = false;
|
||||||
|
if (version > GameVersion::Jak1) {
|
||||||
|
alpha_tpage_flag = proto.flags & 0x4; // tpage-alpha
|
||||||
|
}
|
||||||
|
draw.settings = adgif_to_draw_mode(ag, tdb, map, count, alpha_tpage_flag);
|
||||||
}
|
}
|
||||||
|
|
||||||
ASSERT(frag.vtx_cnt * 3 * sizeof(u16) <= frag.vtx.size());
|
ASSERT(frag.vtx_cnt * 3 * sizeof(u16) <= frag.vtx.size());
|
||||||
|
@ -550,12 +568,13 @@ void extract_shrub(const shrub_types::DrawableTreeInstanceShrub* tree,
|
||||||
const TextureDB& tex_db,
|
const TextureDB& tex_db,
|
||||||
const std::vector<std::pair<int, int>>& /*expected_missing_textures*/,
|
const std::vector<std::pair<int, int>>& /*expected_missing_textures*/,
|
||||||
tfrag3::Level& out,
|
tfrag3::Level& out,
|
||||||
bool dump_level) {
|
bool dump_level,
|
||||||
|
GameVersion version) {
|
||||||
auto& tree_out = out.shrub_trees.emplace_back();
|
auto& tree_out = out.shrub_trees.emplace_back();
|
||||||
auto& protos = tree->info.prototype_inline_array_shrub;
|
auto& protos = tree->info.prototype_inline_array_shrub;
|
||||||
std::vector<ShrubProtoInfo> proto_info;
|
std::vector<ShrubProtoInfo> proto_info;
|
||||||
for (auto& proto : protos.data) {
|
for (auto& proto : protos.data) {
|
||||||
proto_info.push_back(extract_proto(proto, tex_db, map));
|
proto_info.push_back(extract_proto(proto, tex_db, map, version));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto& arr : tree->discovered_arrays) {
|
for (auto& arr : tree->discovered_arrays) {
|
||||||
|
|
|
@ -24,6 +24,7 @@ void extract_shrub(const level_tools::shrub_types::DrawableTreeInstanceShrub* tr
|
||||||
const TextureDB& tex_db,
|
const TextureDB& tex_db,
|
||||||
const std::vector<std::pair<int, int>>& expected_missing_textures,
|
const std::vector<std::pair<int, int>>& expected_missing_textures,
|
||||||
tfrag3::Level& out,
|
tfrag3::Level& out,
|
||||||
bool dump_level);
|
bool dump_level,
|
||||||
|
GameVersion version);
|
||||||
|
|
||||||
} // namespace decompiler
|
} // namespace decompiler
|
||||||
|
|
|
@ -1911,7 +1911,13 @@ void process_draw_mode(std::vector<TFragDraw>& all_draws,
|
||||||
update_mode_from_test1(val, mode);
|
update_mode_from_test1(val, mode);
|
||||||
break;
|
break;
|
||||||
case GsRegisterAddress::TEX0_1:
|
case GsRegisterAddress::TEX0_1:
|
||||||
// ASSERT(val == 0); HACK jak 2 sets this.
|
ASSERT(val == 0 || val == 0x8'0000'0000);
|
||||||
|
if (val == 0x8'0000'0000) {
|
||||||
|
mode.set_decal(true);
|
||||||
|
} else {
|
||||||
|
mode.set_decal(false);
|
||||||
|
}
|
||||||
|
mode.set_tcc(false);
|
||||||
break;
|
break;
|
||||||
case GsRegisterAddress::TEX1_1:
|
case GsRegisterAddress::TEX1_1:
|
||||||
ASSERT(val == 0x120); // some flag
|
ASSERT(val == 0x120); // some flag
|
||||||
|
|
|
@ -34,6 +34,10 @@ SkyBlendHandler::SkyBlendHandler(const std::string& name,
|
||||||
true,
|
true,
|
||||||
level_id) {}
|
level_id) {}
|
||||||
|
|
||||||
|
void SkyBlendHandler::init_shaders(ShaderLibrary& shaders) {
|
||||||
|
m_tfrag_renderer.init_shaders(shaders);
|
||||||
|
}
|
||||||
|
|
||||||
void SkyBlendHandler::handle_sky_copies(DmaFollower& dma,
|
void SkyBlendHandler::handle_sky_copies(DmaFollower& dma,
|
||||||
SharedRenderState* render_state,
|
SharedRenderState* render_state,
|
||||||
ScopedProfilerNode& prof) {
|
ScopedProfilerNode& prof) {
|
||||||
|
|
|
@ -19,6 +19,7 @@ class SkyBlendHandler : public BucketRenderer {
|
||||||
std::shared_ptr<SkyBlendCPU> shared_cpu_blender);
|
std::shared_ptr<SkyBlendCPU> shared_cpu_blender);
|
||||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||||
void draw_debug_window() override;
|
void draw_debug_window() override;
|
||||||
|
void init_shaders(ShaderLibrary& shaders) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_sky_copies(DmaFollower& dma,
|
void handle_sky_copies(DmaFollower& dma,
|
||||||
|
|
|
@ -10,6 +10,10 @@ Shrub::~Shrub() {
|
||||||
discard_tree_cache();
|
discard_tree_cache();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Shrub::init_shaders(ShaderLibrary& shaders) {
|
||||||
|
m_uniforms.decal = glGetUniformLocation(shaders[ShaderId::SHRUB].id(), "decal");
|
||||||
|
}
|
||||||
|
|
||||||
void Shrub::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
void Shrub::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) {
|
||||||
if (!m_enabled) {
|
if (!m_enabled) {
|
||||||
while (dma.current_tag_offset() != render_state->next_bucket) {
|
while (dma.current_tag_offset() != render_state->next_bucket) {
|
||||||
|
@ -298,6 +302,8 @@ void Shrub::render_tree(int idx,
|
||||||
last_texture = draw.tree_tex_id;
|
last_texture = draw.tree_tex_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
glUniform1i(m_uniforms.decal, draw.mode.get_decal() ? 1 : 0);
|
||||||
|
|
||||||
auto double_draw = setup_tfrag_shader(render_state, draw.mode, ShaderId::SHRUB);
|
auto double_draw = setup_tfrag_shader(render_state, draw.mode, ShaderId::SHRUB);
|
||||||
|
|
||||||
prof.add_draw_call();
|
prof.add_draw_call();
|
||||||
|
|
|
@ -13,6 +13,8 @@ class Shrub : public BucketRenderer {
|
||||||
public:
|
public:
|
||||||
Shrub(const std::string& name, int my_id);
|
Shrub(const std::string& name, int my_id);
|
||||||
~Shrub();
|
~Shrub();
|
||||||
|
void init_shaders(ShaderLibrary& shaders) override;
|
||||||
|
|
||||||
bool setup_for_level(const std::string& level, SharedRenderState* render_state);
|
bool setup_for_level(const std::string& level, SharedRenderState* render_state);
|
||||||
void render_all_trees(const TfragRenderSettings& settings,
|
void render_all_trees(const TfragRenderSettings& settings,
|
||||||
SharedRenderState* render_state,
|
SharedRenderState* render_state,
|
||||||
|
@ -53,6 +55,10 @@ class Shrub : public BucketRenderer {
|
||||||
} perf;
|
} perf;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLuint decal;
|
||||||
|
} m_uniforms;
|
||||||
|
|
||||||
std::vector<Tree> m_trees;
|
std::vector<Tree> m_trees;
|
||||||
std::string m_level_name;
|
std::string m_level_name;
|
||||||
const std::vector<GLuint>* m_textures;
|
const std::vector<GLuint>* m_textures;
|
||||||
|
|
|
@ -145,6 +145,10 @@ void TFragment::draw_debug_window() {
|
||||||
m_tfrag3.draw_debug_window();
|
m_tfrag3.draw_debug_window();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TFragment::init_shaders(ShaderLibrary& shaders) {
|
||||||
|
m_tfrag3.init_shaders(shaders);
|
||||||
|
}
|
||||||
|
|
||||||
void TFragment::handle_initialization(DmaFollower& dma) {
|
void TFragment::handle_initialization(DmaFollower& dma) {
|
||||||
// Set up test (different between different renderers)
|
// Set up test (different between different renderers)
|
||||||
auto setup_test = dma.read_and_advance();
|
auto setup_test = dma.read_and_advance();
|
||||||
|
|
|
@ -43,6 +43,7 @@ class TFragment : public BucketRenderer {
|
||||||
int level_id);
|
int level_id);
|
||||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||||
void draw_debug_window() override;
|
void draw_debug_window() override;
|
||||||
|
void init_shaders(ShaderLibrary& shaders) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void handle_initialization(DmaFollower& dma);
|
void handle_initialization(DmaFollower& dma);
|
||||||
|
|
|
@ -40,6 +40,10 @@ Tfrag3::~Tfrag3() {
|
||||||
glDeleteVertexArrays(1, &m_debug_vao);
|
glDeleteVertexArrays(1, &m_debug_vao);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tfrag3::init_shaders(ShaderLibrary& shaders) {
|
||||||
|
m_uniforms.decal = glGetUniformLocation(shaders[ShaderId::TFRAG3].id(), "decal");
|
||||||
|
}
|
||||||
|
|
||||||
void Tfrag3::update_load(const std::vector<tfrag3::TFragmentTreeKind>& tree_kinds,
|
void Tfrag3::update_load(const std::vector<tfrag3::TFragmentTreeKind>& tree_kinds,
|
||||||
const LevelData* loader_data) {
|
const LevelData* loader_data) {
|
||||||
const auto* lev_data = loader_data->level.get();
|
const auto* lev_data = loader_data->level.get();
|
||||||
|
@ -188,15 +192,25 @@ void Tfrag3::render_tree(int geom,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
auto& tree = m_cached_trees.at(geom).at(settings.tree_idx);
|
auto& tree = m_cached_trees.at(geom).at(settings.tree_idx);
|
||||||
|
const auto* itimes = settings.itimes;
|
||||||
|
|
||||||
|
if (tree.freeze_itimes) {
|
||||||
|
itimes = tree.itimes_debug;
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
tree.itimes_debug[i] = settings.itimes[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ASSERT(tree.kind != tfrag3::TFragmentTreeKind::INVALID);
|
ASSERT(tree.kind != tfrag3::TFragmentTreeKind::INVALID);
|
||||||
|
|
||||||
if (m_color_result.size() < tree.colors->size()) {
|
if (m_color_result.size() < tree.colors->size()) {
|
||||||
m_color_result.resize(tree.colors->size());
|
m_color_result.resize(tree.colors->size());
|
||||||
}
|
}
|
||||||
if (m_use_fast_time_of_day) {
|
if (m_use_fast_time_of_day) {
|
||||||
interp_time_of_day_fast(settings.itimes, tree.tod_cache, m_color_result.data());
|
interp_time_of_day_fast(itimes, tree.tod_cache, m_color_result.data());
|
||||||
} else {
|
} else {
|
||||||
interp_time_of_day_slow(settings.itimes, *tree.colors, m_color_result.data());
|
interp_time_of_day_slow(itimes, *tree.colors, m_color_result.data());
|
||||||
}
|
}
|
||||||
glActiveTexture(GL_TEXTURE10);
|
glActiveTexture(GL_TEXTURE10);
|
||||||
glBindTexture(GL_TEXTURE_1D, tree.time_of_day_texture);
|
glBindTexture(GL_TEXTURE_1D, tree.time_of_day_texture);
|
||||||
|
@ -249,6 +263,7 @@ void Tfrag3::render_tree(int geom,
|
||||||
ASSERT(m_textures);
|
ASSERT(m_textures);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_textures->at(draw.tree_tex_id));
|
glBindTexture(GL_TEXTURE_2D, m_textures->at(draw.tree_tex_id));
|
||||||
auto double_draw = setup_tfrag_shader(render_state, draw.mode, ShaderId::TFRAG3);
|
auto double_draw = setup_tfrag_shader(render_state, draw.mode, ShaderId::TFRAG3);
|
||||||
|
glUniform1i(m_uniforms.decal, draw.mode.get_decal() ? 1 : 0);
|
||||||
tree.tris_this_frame += draw.num_triangles;
|
tree.tris_this_frame += draw.num_triangles;
|
||||||
tree.draws_this_frame++;
|
tree.draws_this_frame++;
|
||||||
|
|
||||||
|
@ -347,7 +362,12 @@ void Tfrag3::draw_debug_window() {
|
||||||
ImGui::Checkbox("cull debug (slow)", &tree.cull_debug);
|
ImGui::Checkbox("cull debug (slow)", &tree.cull_debug);
|
||||||
ImGui::PopID();
|
ImGui::PopID();
|
||||||
if (tree.rendered_this_frame) {
|
if (tree.rendered_this_frame) {
|
||||||
|
ImGui::Checkbox("freeze itimes", &tree.freeze_itimes);
|
||||||
ImGui::Text(" tris: %d draws: %d", tree.tris_this_frame, tree.draws_this_frame);
|
ImGui::Text(" tris: %d draws: %d", tree.tris_this_frame, tree.draws_this_frame);
|
||||||
|
for (int j = 0; j < 4; j++) {
|
||||||
|
ImGui::Text(" itimes[%d] 0x%x 0x%x 0x%x 0x%x", j, tree.itimes_debug[j][0],
|
||||||
|
tree.itimes_debug[j][1], tree.itimes_debug[j][2], tree.itimes_debug[j][3]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ class Tfrag3 {
|
||||||
Tfrag3();
|
Tfrag3();
|
||||||
~Tfrag3();
|
~Tfrag3();
|
||||||
|
|
||||||
|
void init_shaders(ShaderLibrary& shaders);
|
||||||
void render_all_trees(int geom,
|
void render_all_trees(int geom,
|
||||||
const TfragRenderSettings& settings,
|
const TfragRenderSettings& settings,
|
||||||
SharedRenderState* render_state,
|
SharedRenderState* render_state,
|
||||||
|
@ -78,8 +79,15 @@ class Tfrag3 {
|
||||||
bool allowed = true;
|
bool allowed = true;
|
||||||
bool forced = false;
|
bool forced = false;
|
||||||
bool cull_debug = false;
|
bool cull_debug = false;
|
||||||
|
|
||||||
|
bool freeze_itimes = false;
|
||||||
|
math::Vector<s32, 4> itimes_debug[4];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct {
|
||||||
|
GLuint decal;
|
||||||
|
} m_uniforms;
|
||||||
|
|
||||||
struct Cache {
|
struct Cache {
|
||||||
std::vector<u8> vis_temp;
|
std::vector<u8> vis_temp;
|
||||||
std::vector<std::pair<int, int>> draw_idx_temp;
|
std::vector<std::pair<int, int>> draw_idx_temp;
|
||||||
|
|
|
@ -218,6 +218,7 @@ void interp_time_of_day_slow(const math::Vector<s32, 4> itimes[4],
|
||||||
}
|
}
|
||||||
// result += in[color].rgba[component].cast<float>() * weights[component];
|
// result += in[color].rgba[component].cast<float>() * weights[component];
|
||||||
}
|
}
|
||||||
|
|
||||||
result[0] = std::min(result[0], 255.f);
|
result[0] = std::min(result[0], 255.f);
|
||||||
result[1] = std::min(result[1], 255.f);
|
result[1] = std::min(result[1], 255.f);
|
||||||
result[2] = std::min(result[2], 255.f);
|
result[2] = std::min(result[2], 255.f);
|
||||||
|
@ -349,15 +350,15 @@ void interp_time_of_day_fast(const math::Vector<s32, 4> itimes[4],
|
||||||
color7 = _mm_mullo_epi16(color7, weights7);
|
color7 = _mm_mullo_epi16(color7, weights7);
|
||||||
|
|
||||||
// add. This order minimizes dependencies.
|
// add. This order minimizes dependencies.
|
||||||
color0 = _mm_add_epi16(color0, color1);
|
color0 = _mm_adds_epi16(color0, color1);
|
||||||
color2 = _mm_add_epi16(color2, color3);
|
color2 = _mm_adds_epi16(color2, color3);
|
||||||
color4 = _mm_add_epi16(color4, color5);
|
color4 = _mm_adds_epi16(color4, color5);
|
||||||
color6 = _mm_add_epi16(color6, color7);
|
color6 = _mm_adds_epi16(color6, color7);
|
||||||
|
|
||||||
color0 = _mm_add_epi16(color0, color2);
|
color0 = _mm_adds_epi16(color0, color2);
|
||||||
color4 = _mm_add_epi16(color4, color6);
|
color4 = _mm_adds_epi16(color4, color6);
|
||||||
|
|
||||||
color0 = _mm_add_epi16(color0, color4);
|
color0 = _mm_adds_epi16(color0, color4);
|
||||||
|
|
||||||
// divide, because we multiplied our weights by 2^7.
|
// divide, because we multiplied our weights by 2^7.
|
||||||
color0 = _mm_srli_epi16(color0, 6);
|
color0 = _mm_srli_epi16(color0, 6);
|
||||||
|
@ -404,15 +405,15 @@ void interp_time_of_day_fast(const math::Vector<s32, 4> itimes[4],
|
||||||
color7 = _mm_mullo_epi16(color7, weights7);
|
color7 = _mm_mullo_epi16(color7, weights7);
|
||||||
|
|
||||||
// add. This order minimizes dependencies.
|
// add. This order minimizes dependencies.
|
||||||
color0 = _mm_add_epi16(color0, color1);
|
color0 = _mm_adds_epi16(color0, color1);
|
||||||
color2 = _mm_add_epi16(color2, color3);
|
color2 = _mm_adds_epi16(color2, color3);
|
||||||
color4 = _mm_add_epi16(color4, color5);
|
color4 = _mm_adds_epi16(color4, color5);
|
||||||
color6 = _mm_add_epi16(color6, color7);
|
color6 = _mm_adds_epi16(color6, color7);
|
||||||
|
|
||||||
color0 = _mm_add_epi16(color0, color2);
|
color0 = _mm_adds_epi16(color0, color2);
|
||||||
color4 = _mm_add_epi16(color4, color6);
|
color4 = _mm_adds_epi16(color4, color6);
|
||||||
|
|
||||||
color0 = _mm_add_epi16(color0, color4);
|
color0 = _mm_adds_epi16(color0, color4);
|
||||||
|
|
||||||
// divide, because we multiplied our weights by 2^7.
|
// divide, because we multiplied our weights by 2^7.
|
||||||
color0 = _mm_srli_epi16(color0, 6);
|
color0 = _mm_srli_epi16(color0, 6);
|
||||||
|
|
|
@ -10,6 +10,7 @@ uniform mat4 camera;
|
||||||
uniform float fog_constant;
|
uniform float fog_constant;
|
||||||
uniform float fog_min;
|
uniform float fog_min;
|
||||||
uniform float fog_max;
|
uniform float fog_max;
|
||||||
|
uniform int decal;
|
||||||
layout (binding = 10) uniform sampler1D tex_T1; // note, sampled in the vertex shader on purpose.
|
layout (binding = 10) uniform sampler1D tex_T1; // note, sampled in the vertex shader on purpose.
|
||||||
|
|
||||||
out vec4 fragment_color;
|
out vec4 fragment_color;
|
||||||
|
@ -72,6 +73,10 @@ void main() {
|
||||||
fragment_color *= tod_color * 4;
|
fragment_color *= tod_color * 4;
|
||||||
fragment_color.a *= 2;
|
fragment_color.a *= 2;
|
||||||
|
|
||||||
|
if (decal == 1) {
|
||||||
|
fragment_color.xyz = vec3(1.0, 1.0, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
tex_coord = tex_coord_in;
|
tex_coord = tex_coord_in;
|
||||||
tex_coord.xy /= 4096;
|
tex_coord.xy /= 4096;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,14 +64,15 @@ void main() {
|
||||||
transformed.y *= SCISSOR_ADJUST * HEIGHT_SCALE;
|
transformed.y *= SCISSOR_ADJUST * HEIGHT_SCALE;
|
||||||
gl_Position = transformed;
|
gl_Position = transformed;
|
||||||
|
|
||||||
|
// time of day lookup
|
||||||
|
fragment_color = texelFetch(tex_T1, time_of_day_index, 0);
|
||||||
|
// color adjustment
|
||||||
|
fragment_color *= 2;
|
||||||
|
fragment_color.a *= 2;
|
||||||
|
|
||||||
if (decal == 1) {
|
if (decal == 1) {
|
||||||
fragment_color = vec4(1.0, 1.0, 1.0, 1.0);
|
// tfrag/tie always use TCC=RGB, so even with decal, alpha comes from fragment.
|
||||||
} else {
|
fragment_color.xyz = vec3(1.0, 1.0, 1.0);
|
||||||
// time of day lookup
|
|
||||||
fragment_color = texelFetch(tex_T1, time_of_day_index, 0);
|
|
||||||
// color adjustment
|
|
||||||
fragment_color *= 2;
|
|
||||||
fragment_color.a *= 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fog hack
|
// fog hack
|
||||||
|
|
Loading…
Reference in a new issue