mirror of
https://github.com/open-goal/jak-project.git
synced 2024-10-20 11:26:18 -04:00
add fog (#1204)
This commit is contained in:
parent
b55de36b27
commit
382ec1d1c5
|
@ -92,6 +92,8 @@ struct SharedRenderState {
|
|||
bool render_debug = false;
|
||||
bool enable_merc_xgkick = true;
|
||||
bool enable_generic_xgkick = true;
|
||||
math::Vector<u8, 4> fog_color;
|
||||
float fog_intensity = 1.f;
|
||||
|
||||
void reset();
|
||||
bool has_camera_planes = false;
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
#include "third-party/imgui/imgui.h"
|
||||
#include "common/util/Assert.h"
|
||||
|
||||
DirectRenderer::DirectRenderer(const std::string& name, BucketId my_id, int batch_size, Mode mode)
|
||||
: BucketRenderer(name, my_id), m_prim_buffer(batch_size), m_mode(mode) {
|
||||
DirectRenderer::DirectRenderer(const std::string& name, BucketId my_id, int batch_size)
|
||||
: BucketRenderer(name, my_id), m_prim_buffer(batch_size) {
|
||||
glGenBuffers(1, &m_ogl.vertex_buffer);
|
||||
glGenVertexArrays(1, &m_ogl.vao);
|
||||
glBindVertexArray(m_ogl.vao);
|
||||
|
@ -17,12 +17,12 @@ DirectRenderer::DirectRenderer(const std::string& name, BucketId my_id, int batc
|
|||
glBufferData(GL_ARRAY_BUFFER, m_ogl.vertex_buffer_bytes, nullptr,
|
||||
GL_STREAM_DRAW); // todo stream?
|
||||
glEnableVertexAttribArray(0);
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
4, // 4 floats per vert (w unused)
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, xyz) // offset in array (why is this a pointer...)
|
||||
glVertexAttribPointer(0, // location 0 in the shader
|
||||
4, // 4 floats per vert (w unused)
|
||||
GL_FLOAT, // floats
|
||||
GL_TRUE, // normalized, ignored,
|
||||
sizeof(Vertex), //
|
||||
(void*)offsetof(Vertex, xyzf) // offset in array (why is this a pointer...)
|
||||
);
|
||||
|
||||
glEnableVertexAttribArray(1);
|
||||
|
@ -123,10 +123,6 @@ void DirectRenderer::draw_debug_window() {
|
|||
ImGui::SameLine();
|
||||
ImGui::Checkbox("no mip", &m_debug_state.disable_mipmap);
|
||||
|
||||
if (m_mode == Mode::SPRITE_CPU) {
|
||||
ImGui::Checkbox("draw1", &m_sprite_mode.do_first_draw);
|
||||
}
|
||||
|
||||
ImGui::Text("Triangles: %d", m_stats.triangles);
|
||||
ImGui::SameLine();
|
||||
ImGui::Text("Draws: %d", m_stats.draw_calls);
|
||||
|
@ -193,6 +189,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state, ScopedProfil
|
|||
if (m_debug_state.disable_texture) {
|
||||
// a bit of a hack, this forces the non-textured shader always.
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
m_blend_state_needs_gl_update = true;
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
}
|
||||
|
||||
if (m_debug_state.red) {
|
||||
|
@ -216,23 +214,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state, ScopedProfil
|
|||
m_prim_buffer.vertices.data(), GL_STREAM_DRAW);
|
||||
|
||||
int draw_count = 0;
|
||||
if (m_mode == Mode::SPRITE_CPU) {
|
||||
if (!m_prim_gl_state.texture_enable) {
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
} else {
|
||||
// ASSERT(m_global_texture_state.tcc);
|
||||
ASSERT(m_prim_gl_state.texture_enable);
|
||||
render_state->shaders[ShaderId::SPRITE_CPU].activate();
|
||||
}
|
||||
|
||||
if (m_sprite_mode.do_first_draw) {
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
|
||||
draw_count++;
|
||||
}
|
||||
} else {
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
|
||||
draw_count++;
|
||||
}
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
|
||||
draw_count++;
|
||||
|
||||
if (m_debug_state.wireframe) {
|
||||
render_state->shaders[ShaderId::DEBUG_RED].activate();
|
||||
|
@ -240,6 +223,8 @@ void DirectRenderer::flush_pending(SharedRenderState* render_state, ScopedProfil
|
|||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDrawArrays(GL_TRIANGLES, 0, m_prim_buffer.vert_count);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
m_blend_state_needs_gl_update = true;
|
||||
m_prim_gl_state_needs_gl_update = true;
|
||||
draw_count++;
|
||||
}
|
||||
|
||||
|
@ -272,25 +257,21 @@ void DirectRenderer::update_gl_prim(SharedRenderState* render_state) {
|
|||
ASSERT(false);
|
||||
}
|
||||
}
|
||||
if (m_mode == Mode::SPRITE_CPU) {
|
||||
render_state->shaders[ShaderId::SPRITE_CPU].activate();
|
||||
} else if (m_mode == Mode::SKY) {
|
||||
ASSERT(false);
|
||||
} else {
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].activate();
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
|
||||
"alpha_reject"),
|
||||
alpha_reject);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
|
||||
"color_mult"),
|
||||
m_ogl.color_mult);
|
||||
}
|
||||
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].activate();
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
|
||||
"alpha_reject"),
|
||||
alpha_reject);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
|
||||
"color_mult"),
|
||||
m_ogl.color_mult);
|
||||
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::DIRECT_BASIC_TEXTURED].id(),
|
||||
"fog_color"),
|
||||
render_state->fog_color[0], render_state->fog_color[1], render_state->fog_color[2],
|
||||
render_state->fog_intensity);
|
||||
|
||||
} else {
|
||||
if (m_mode == Mode::SKY) {
|
||||
render_state->shaders[ShaderId::SKY].activate();
|
||||
} else {
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
}
|
||||
render_state->shaders[ShaderId::DIRECT_BASIC].activate();
|
||||
}
|
||||
if (state.fogging_enable) {
|
||||
// ASSERT(false);
|
||||
|
@ -932,7 +913,8 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
bool advance) {
|
||||
ASSERT(z < (1 << 24));
|
||||
(void)f; // TODO: do something with this.
|
||||
if (m_my_id == BucketId::GENERIC_PRIS) {
|
||||
|
||||
if (m_my_id == BucketId::MERC_TFRAG_TEX_LEVEL0) {
|
||||
// fmt::print("0x{:x}, 0x{:x}, 0x{:x}\n", x, y, z);
|
||||
}
|
||||
if (m_prim_buffer.is_full()) {
|
||||
|
@ -945,13 +927,14 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
m_prim_building.st_reg.x(), m_prim_building.st_reg.y(), m_prim_building.Q);
|
||||
m_prim_building.building_rgba.at(m_prim_building.building_idx) = m_prim_building.rgba_reg;
|
||||
m_prim_building.building_vert.at(m_prim_building.building_idx) =
|
||||
math::Vector<u32, 3>{x << 16, y << 16, z << 8};
|
||||
math::Vector<u32, 4>{x << 16, y << 16, z << 8, f};
|
||||
|
||||
m_prim_building.building_idx++;
|
||||
|
||||
int tex_unit = get_texture_unit_for_current_reg(render_state, prof);
|
||||
bool tcc = m_buffered_tex_state[tex_unit].tcc;
|
||||
bool decal = m_buffered_tex_state[tex_unit].decal;
|
||||
bool fge = m_prim_gl_state.fogging_enable;
|
||||
|
||||
switch (m_prim_building.kind) {
|
||||
case GsPrim::Kind::SPRITE: {
|
||||
|
@ -962,8 +945,8 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
auto& corner2_vert = m_prim_building.building_vert[1];
|
||||
auto& corner2_rgba = m_prim_building.building_rgba[1];
|
||||
// should use most recent vertex z.
|
||||
math::Vector<u32, 3> corner3_vert{corner1_vert[0], corner2_vert[1], corner2_vert[2]};
|
||||
math::Vector<u32, 3> corner4_vert{corner2_vert[0], corner1_vert[1], corner2_vert[2]};
|
||||
math::Vector<u32, 4> corner3_vert{corner1_vert[0], corner2_vert[1], corner2_vert[2]};
|
||||
math::Vector<u32, 4> corner4_vert{corner2_vert[0], corner1_vert[1], corner2_vert[2]};
|
||||
|
||||
if (m_prim_gl_state.gouraud_enable) {
|
||||
// I'm not really sure what the GS does here.
|
||||
|
@ -972,12 +955,12 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
auto& corner3_rgba = corner2_rgba;
|
||||
auto& corner4_rgba = corner2_rgba;
|
||||
|
||||
m_prim_buffer.push(corner1_rgba, corner1_vert, {}, 0, tcc, decal);
|
||||
m_prim_buffer.push(corner3_rgba, corner3_vert, {}, 0, tcc, decal);
|
||||
m_prim_buffer.push(corner2_rgba, corner2_vert, {}, 0, tcc, decal);
|
||||
m_prim_buffer.push(corner2_rgba, corner2_vert, {}, 0, tcc, decal);
|
||||
m_prim_buffer.push(corner4_rgba, corner4_vert, {}, 0, tcc, decal);
|
||||
m_prim_buffer.push(corner1_rgba, corner1_vert, {}, 0, tcc, decal);
|
||||
m_prim_buffer.push(corner1_rgba, corner1_vert, {}, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner3_rgba, corner3_vert, {}, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner2_rgba, corner2_vert, {}, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner2_rgba, corner2_vert, {}, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner4_rgba, corner4_vert, {}, 0, tcc, decal, fge);
|
||||
m_prim_buffer.push(corner1_rgba, corner1_vert, {}, 0, tcc, decal, fge);
|
||||
m_prim_building.building_idx = 0;
|
||||
}
|
||||
} break;
|
||||
|
@ -993,7 +976,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
if (advance) {
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal);
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1005,7 +988,7 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
m_prim_building.building_idx = 0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal);
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1021,15 +1004,15 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
}
|
||||
for (int i = 0; i < 3; i++) {
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[i], m_prim_building.building_vert[i],
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal);
|
||||
m_prim_building.building_stq[i], tex_unit, tcc, decal, fge);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
|
||||
case GsPrim::Kind::LINE: {
|
||||
if (m_prim_building.building_idx == 2) {
|
||||
math::Vector<double, 3> pt0 = m_prim_building.building_vert[0].cast<double>();
|
||||
math::Vector<double, 3> pt1 = m_prim_building.building_vert[1].cast<double>();
|
||||
math::Vector<double, 3> pt0 = m_prim_building.building_vert[0].xyz().cast<double>();
|
||||
math::Vector<double, 3> pt1 = m_prim_building.building_vert[1].xyz().cast<double>();
|
||||
auto normal = (pt1 - pt0).normalized().cross(math::Vector<double, 3>{0, 0, 1});
|
||||
|
||||
double line_width = (1 << 19);
|
||||
|
@ -1040,15 +1023,19 @@ void DirectRenderer::handle_xyzf2_common(u32 x,
|
|||
math::Vector<double, 3> b = pt1 + normal * line_width;
|
||||
math::Vector<double, 3> c = pt0 - normal * line_width;
|
||||
math::Vector<double, 3> d = pt1 - normal * line_width;
|
||||
math::Vector<u32, 4> ai{a.x(), a.y(), a.z(), 0};
|
||||
math::Vector<u32, 4> bi{b.x(), b.y(), b.z(), 0};
|
||||
math::Vector<u32, 4> ci{c.x(), c.y(), c.z(), 0};
|
||||
math::Vector<u32, 4> di{d.x(), d.y(), d.z(), 0};
|
||||
|
||||
// ACB:
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], a.cast<u32>(), {}, 0, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], c.cast<u32>(), {}, 0, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], b.cast<u32>(), {}, 0, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ai, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false);
|
||||
// b c d
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], b.cast<u32>(), {}, 0, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], c.cast<u32>(), {}, 0, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], d.cast<u32>(), {}, 0, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], bi, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[0], ci, {}, 0, false, false, false);
|
||||
m_prim_buffer.push(m_prim_building.building_rgba[1], di, {}, 0, false, false, false);
|
||||
//
|
||||
|
||||
m_prim_building.building_idx = 0;
|
||||
|
@ -1115,19 +1102,22 @@ DirectRenderer::PrimitiveBuffer::PrimitiveBuffer(int max_triangles) {
|
|||
}
|
||||
|
||||
void DirectRenderer::PrimitiveBuffer::push(const math::Vector<u8, 4>& rgba,
|
||||
const math::Vector<u32, 3>& vert,
|
||||
const math::Vector<u32, 4>& vert,
|
||||
const math::Vector<float, 3>& st,
|
||||
int unit,
|
||||
bool tcc,
|
||||
bool decal) {
|
||||
bool decal,
|
||||
bool fog_enable) {
|
||||
auto& v = vertices[vert_count];
|
||||
v.rgba = rgba;
|
||||
v.xyz[0] = (float)vert[0] / (float)UINT32_MAX;
|
||||
v.xyz[1] = (float)vert[1] / (float)UINT32_MAX;
|
||||
v.xyz[2] = (float)vert[2] / (float)UINT32_MAX;
|
||||
v.xyzf[0] = (float)vert[0] / (float)UINT32_MAX;
|
||||
v.xyzf[1] = (float)vert[1] / (float)UINT32_MAX;
|
||||
v.xyzf[2] = (float)vert[2] / (float)UINT32_MAX;
|
||||
v.xyzf[3] = (float)vert[3];
|
||||
v.stq = st;
|
||||
v.tex_unit = unit;
|
||||
v.tcc = tcc;
|
||||
v.decal = decal;
|
||||
v.fog_enable = fog_enable;
|
||||
vert_count++;
|
||||
}
|
||||
|
|
|
@ -19,13 +19,7 @@
|
|||
*/
|
||||
class DirectRenderer : public BucketRenderer {
|
||||
public:
|
||||
// specializations of direct renderer to handle certain outputs.
|
||||
enum class Mode {
|
||||
NORMAL, // use for general debug drawing, font.
|
||||
SPRITE_CPU, // use for sprites (does the appropriate alpha test tricks)
|
||||
SKY // disables texture perspective correction
|
||||
};
|
||||
DirectRenderer(const std::string& name, BucketId my_id, int batch_size, Mode mode);
|
||||
DirectRenderer(const std::string& name, BucketId my_id, int batch_size);
|
||||
~DirectRenderer();
|
||||
void render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfilerNode& prof) override;
|
||||
|
||||
|
@ -199,7 +193,7 @@ class DirectRenderer : public BucketRenderer {
|
|||
math::Vector<float, 2> st_reg;
|
||||
|
||||
std::array<math::Vector<u8, 4>, 3> building_rgba;
|
||||
std::array<math::Vector<u32, 3>, 3> building_vert;
|
||||
std::array<math::Vector<u32, 4>, 3> building_vert;
|
||||
std::array<math::Vector<float, 3>, 3> building_stq;
|
||||
int building_idx = 0;
|
||||
int tri_strip_startup = 0;
|
||||
|
@ -209,13 +203,14 @@ class DirectRenderer : public BucketRenderer {
|
|||
} m_prim_building;
|
||||
|
||||
struct Vertex {
|
||||
math::Vector<float, 4> xyz;
|
||||
math::Vector<float, 4> xyzf;
|
||||
math::Vector<float, 3> stq;
|
||||
math::Vector<u8, 4> rgba;
|
||||
u8 tex_unit;
|
||||
u8 tcc;
|
||||
u8 decal;
|
||||
math::Vector<u8, 29> pad;
|
||||
u8 fog_enable;
|
||||
math::Vector<u8, 28> pad;
|
||||
};
|
||||
static_assert(sizeof(Vertex) == 64);
|
||||
static_assert(offsetof(Vertex, tex_unit) == 32);
|
||||
|
@ -229,11 +224,12 @@ class DirectRenderer : public BucketRenderer {
|
|||
// leave 6 free on the end so we always have room to flush one last primitive.
|
||||
bool is_full() { return max_verts < (vert_count + 18); }
|
||||
void push(const math::Vector<u8, 4>& rgba,
|
||||
const math::Vector<u32, 3>& vert,
|
||||
const math::Vector<u32, 4>& vert,
|
||||
const math::Vector<float, 3>& stq,
|
||||
int unit,
|
||||
bool tcc,
|
||||
bool decal);
|
||||
bool decal,
|
||||
bool fog_enable);
|
||||
} m_prim_buffer;
|
||||
|
||||
struct {
|
||||
|
@ -273,6 +269,4 @@ class DirectRenderer : public BucketRenderer {
|
|||
struct SpriteMode {
|
||||
bool do_first_draw = true;
|
||||
} m_sprite_mode;
|
||||
|
||||
Mode m_mode;
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#include "third-party/imgui/imgui.h"
|
||||
|
||||
GenericRenderer::GenericRenderer(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id), m_direct(name, my_id, 0x4000, DirectRenderer::Mode::NORMAL) {}
|
||||
: BucketRenderer(name, my_id), m_direct(name, my_id, 0x4000) {}
|
||||
|
||||
void GenericRenderer::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
#include "third-party/imgui/imgui.h"
|
||||
|
||||
MercRenderer::MercRenderer(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id),
|
||||
m_direct(fmt::format("{}-dir", name), my_id, 0x30000, DirectRenderer::Mode::NORMAL) {
|
||||
: BucketRenderer(name, my_id), m_direct(fmt::format("{}-dir", name), my_id, 0x30000) {
|
||||
memset(m_buffer.data, 0, sizeof(m_buffer.data));
|
||||
}
|
||||
|
||||
|
|
|
@ -211,10 +211,8 @@ void OpenGLRenderer::init_bucket_renderers() {
|
|||
sprite_renderers.push_back(std::make_unique<SpriteRenderer>("sprite-renderer", BucketId::SPRITE));
|
||||
init_bucket_renderer<RenderMux>("sprite", BucketId::SPRITE, std::move(sprite_renderers)); // 66
|
||||
|
||||
init_bucket_renderer<DirectRenderer>("debug-draw-0", BucketId::DEBUG_DRAW_0, 0x20000,
|
||||
DirectRenderer::Mode::NORMAL);
|
||||
init_bucket_renderer<DirectRenderer>("debug-draw-1", BucketId::DEBUG_DRAW_1, 0x8000,
|
||||
DirectRenderer::Mode::NORMAL);
|
||||
init_bucket_renderer<DirectRenderer>("debug-draw-0", BucketId::DEBUG_DRAW_0, 0x20000);
|
||||
init_bucket_renderer<DirectRenderer>("debug-draw-1", BucketId::DEBUG_DRAW_1, 0x8000);
|
||||
|
||||
// for now, for any unset renderers, just set them to an EmptyBucketRenderer.
|
||||
for (size_t i = 0; i < m_bucket_renderers.size(); i++) {
|
||||
|
@ -266,6 +264,10 @@ void OpenGLRenderer::render(DmaFollower dma, const RenderOptions& settings) {
|
|||
m_profiler.draw();
|
||||
}
|
||||
|
||||
if (settings.draw_small_profiler_window) {
|
||||
m_profiler.draw_small_window();
|
||||
}
|
||||
|
||||
if (settings.save_screenshot) {
|
||||
finish_screenshot(settings.screenshot_path, settings.window_width_px, settings.window_height_px,
|
||||
settings.lbox_width_px, settings.lbox_height_px);
|
||||
|
@ -287,6 +289,7 @@ void OpenGLRenderer::serialize(Serializer& ser) {
|
|||
void OpenGLRenderer::draw_renderer_selection_window() {
|
||||
ImGui::Begin("Renderer Debug");
|
||||
|
||||
ImGui::SliderFloat("Fog Adjust", &m_render_state.fog_intensity, 0, 10);
|
||||
ImGui::Checkbox("Sky CPU", &m_render_state.use_sky_cpu);
|
||||
ImGui::Checkbox("Occlusion Cull", &m_render_state.use_occlusion_culling);
|
||||
ImGui::Checkbox("Render Debug (slower)", &m_render_state.render_debug);
|
||||
|
@ -348,7 +351,9 @@ void OpenGLRenderer::dispatch_buckets(DmaFollower dma, ScopedProfilerNode& prof)
|
|||
ASSERT(default_regs_tag.kind == DmaTag::Kind::CNT);
|
||||
ASSERT(default_regs_tag.qwc == 10);
|
||||
// TODO verify data in here.
|
||||
dma.read_and_advance();
|
||||
auto default_data = dma.read_and_advance();
|
||||
ASSERT(default_data.size_bytes > 148);
|
||||
memcpy(m_render_state.fog_color.data(), default_data.data + 144, 4);
|
||||
auto default_ret_tag = dma.current_tag();
|
||||
ASSERT(default_ret_tag.qwc == 0);
|
||||
ASSERT(default_ret_tag.kind == DmaTag::Kind::RET);
|
||||
|
|
|
@ -15,6 +15,7 @@ struct RenderOptions {
|
|||
int lbox_width_px = 0;
|
||||
bool draw_render_debug_window = false;
|
||||
bool draw_profiler_window = false;
|
||||
bool draw_small_profiler_window = false;
|
||||
bool playing_from_dump = false;
|
||||
|
||||
bool save_screenshot = false;
|
||||
|
|
|
@ -88,6 +88,31 @@ void Profiler::draw() {
|
|||
ImGui::End();
|
||||
}
|
||||
|
||||
void Profiler::draw_small_window() {
|
||||
ImGuiWindowFlags window_flags = ImGuiWindowFlags_NoDecoration |
|
||||
ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_NoSavedSettings |
|
||||
ImGuiWindowFlags_NoFocusOnAppearing | ImGuiWindowFlags_NoNav;
|
||||
auto* p_open = &m_small_window_open;
|
||||
const float PAD = 10.0f;
|
||||
const ImGuiViewport* viewport = ImGui::GetMainViewport();
|
||||
ImVec2 work_pos = viewport->WorkPos; // Use work area to avoid menu-bar/task-bar, if any!
|
||||
ImVec2 work_size = viewport->WorkSize;
|
||||
ImVec2 window_pos, window_pos_pivot;
|
||||
window_pos.x = (work_pos.x + PAD);
|
||||
window_pos.y = (work_pos.y + work_size.y - PAD);
|
||||
window_pos_pivot.x = 0.0f;
|
||||
window_pos_pivot.y = 1.0f;
|
||||
ImGui::SetNextWindowPos(window_pos, ImGuiCond_Always, window_pos_pivot);
|
||||
|
||||
ImGui::SetNextWindowBgAlpha(0.85f); // Transparent background
|
||||
if (ImGui::Begin("Profiler (short)", p_open, window_flags)) {
|
||||
ImGui::Text(" tri: %7d\n", m_root.m_stats.triangles);
|
||||
ImGui::Text(" DC: %4d\n", m_root.m_stats.draw_calls);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
u32 name_to_color(const std::string& name) {
|
||||
u64 val = std::hash<std::string>{}(name);
|
||||
return colors::common_colors[val % colors::COLOR_COUNT] | 0xff000000;
|
||||
|
|
|
@ -67,6 +67,7 @@ class Profiler {
|
|||
Profiler();
|
||||
void clear();
|
||||
void draw();
|
||||
void draw_small_window();
|
||||
void finish();
|
||||
ProfilerNode* root() { return &m_root; }
|
||||
|
||||
|
@ -79,5 +80,6 @@ class Profiler {
|
|||
};
|
||||
|
||||
int m_mode_selector = 0;
|
||||
bool m_small_window_open = true;
|
||||
ProfilerNode m_root;
|
||||
};
|
|
@ -25,19 +25,13 @@ enum class ShaderId {
|
|||
TEST_SHADER = 0,
|
||||
DIRECT_BASIC = 1,
|
||||
DIRECT_BASIC_TEXTURED = 2,
|
||||
// DIRECT_BASIC_TEXTURED_TCC0 = 3,
|
||||
DEBUG_RED = 4,
|
||||
SPRITE_CPU = 5,
|
||||
// SPRITE_CPU_AFAIL = 6,
|
||||
SKY = 7,
|
||||
SKY_BLEND = 8,
|
||||
// DEBUG_BUFFERED = 9,
|
||||
// BUFFERED_TCC0 = 10,
|
||||
// BUFFERED_TCC1 = 11,
|
||||
TFRAG3 = 12,
|
||||
TFRAG3_NO_TEX = 13,
|
||||
SPRITE = 14,
|
||||
SPRITE3 = 15,
|
||||
DEBUG_RED = 3,
|
||||
SKY = 4,
|
||||
SKY_BLEND = 5,
|
||||
TFRAG3 = 6,
|
||||
TFRAG3_NO_TEX = 7,
|
||||
SPRITE = 8,
|
||||
SPRITE3 = 9,
|
||||
MAX_SHADERS
|
||||
};
|
||||
|
||||
|
|
|
@ -120,8 +120,7 @@ void SkyBlendHandler::draw_debug_window() {
|
|||
}
|
||||
|
||||
SkyRenderer::SkyRenderer(const std::string& name, BucketId my_id)
|
||||
: BucketRenderer(name, my_id),
|
||||
m_direct_renderer("sky-direct", my_id, 100, DirectRenderer::Mode::NORMAL) {}
|
||||
: BucketRenderer(name, my_id), m_direct_renderer("sky-direct", my_id, 100) {}
|
||||
|
||||
void SkyRenderer::render(DmaFollower& dma,
|
||||
SharedRenderState* render_state,
|
||||
|
|
|
@ -92,6 +92,7 @@ void OpenGlDebugGui::draw(const DmaStats& dma_stats) {
|
|||
ImGui::MenuItem("Frame Time Plot", nullptr, &m_draw_frame_time);
|
||||
ImGui::MenuItem("Render Debug", nullptr, &m_draw_debug);
|
||||
ImGui::MenuItem("Profiler", nullptr, &m_draw_profiler);
|
||||
ImGui::MenuItem("Small Profiler", nullptr, &small_profiler);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ class OpenGlDebugGui {
|
|||
float target_fps = 60.f;
|
||||
bool experimental_accurate_lag = false;
|
||||
bool sleep_in_frame_limiter = true;
|
||||
bool small_profiler = true;
|
||||
|
||||
private:
|
||||
FrameTimeRecorder m_frame_timer;
|
||||
|
|
|
@ -6,8 +6,10 @@ in vec4 fragment_color;
|
|||
in vec3 tex_coord;
|
||||
uniform float alpha_reject;
|
||||
uniform float color_mult;
|
||||
uniform vec4 fog_color;
|
||||
|
||||
in flat uvec4 tex_info;
|
||||
in float fog;
|
||||
|
||||
layout (binding = 20) uniform sampler2D tex_T0;
|
||||
layout (binding = 21) uniform sampler2D tex_T1;
|
||||
|
@ -21,49 +23,52 @@ layout (binding = 28) uniform sampler2D tex_T8;
|
|||
layout (binding = 29) uniform sampler2D tex_T9;
|
||||
|
||||
vec4 sample_tex(vec2 coord, uint unit) {
|
||||
switch (unit) {
|
||||
case 0: return texture(tex_T0, coord);
|
||||
case 1: return texture(tex_T1, coord);
|
||||
case 2: return texture(tex_T2, coord);
|
||||
case 3: return texture(tex_T3, coord);
|
||||
case 4: return texture(tex_T4, coord);
|
||||
case 5: return texture(tex_T5, coord);
|
||||
case 6: return texture(tex_T6, coord);
|
||||
case 7: return texture(tex_T7, coord);
|
||||
case 8: return texture(tex_T8, coord);
|
||||
case 9: return texture(tex_T9, coord);
|
||||
default: return vec4(1.0, 0, 1.0, 1.0);
|
||||
}
|
||||
switch (unit) {
|
||||
case 0: return texture(tex_T0, coord);
|
||||
case 1: return texture(tex_T1, coord);
|
||||
case 2: return texture(tex_T2, coord);
|
||||
case 3: return texture(tex_T3, coord);
|
||||
case 4: return texture(tex_T4, coord);
|
||||
case 5: return texture(tex_T5, coord);
|
||||
case 6: return texture(tex_T6, coord);
|
||||
case 7: return texture(tex_T7, coord);
|
||||
case 8: return texture(tex_T8, coord);
|
||||
case 9: return texture(tex_T9, coord);
|
||||
default : return vec4(1.0, 0, 1.0, 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
vec4 T0 = sample_tex(tex_coord.xy / tex_coord.z, tex_info.x);
|
||||
// y is tcc
|
||||
// z is decal
|
||||
vec4 T0 = sample_tex(tex_coord.xy / tex_coord.z, tex_info.x);
|
||||
// y is tcc
|
||||
// z is decal
|
||||
|
||||
if (tex_info.y == 0) {
|
||||
if (tex_info.z == 0) {
|
||||
// modulate + no tcc
|
||||
color.xyz = fragment_color.xyz * T0.xyz;
|
||||
color.w = fragment_color.w;
|
||||
if (tex_info.y == 0) {
|
||||
if (tex_info.z == 0) {
|
||||
// modulate + no tcc
|
||||
color.xyz = fragment_color.xyz * T0.xyz;
|
||||
color.w = fragment_color.w;
|
||||
} else {
|
||||
// decal + no tcc
|
||||
color.xyz = T0.xyz * 0.5;
|
||||
color.w = fragment_color.w;
|
||||
}
|
||||
} else {
|
||||
// decal + no tcc
|
||||
color.xyz = T0.xyz * 0.5;
|
||||
color.w = fragment_color.w;
|
||||
if (tex_info.z == 0) {
|
||||
// modulate + tcc
|
||||
color = fragment_color * T0;
|
||||
} else {
|
||||
// decal + tcc
|
||||
color.xyz = T0.xyz * 0.5;
|
||||
color.w = T0.w;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (tex_info.z == 0) {
|
||||
// modulate + tcc
|
||||
color = fragment_color * T0;
|
||||
} else {
|
||||
// decal + tcc
|
||||
color.xyz = T0.xyz * 0.5;
|
||||
color.w = T0.w;
|
||||
color *= 2;
|
||||
color.xyz *= color_mult;
|
||||
if (color.a < alpha_reject) {
|
||||
discard;
|
||||
}
|
||||
if (tex_info.w == 1) {
|
||||
color.xyz = mix(color.xyz, fog_color.xyz / 255., clamp(fog_color.w * (1 - fog), 0, 1));
|
||||
}
|
||||
}
|
||||
color *= 2;
|
||||
color.xyz *= color_mult;
|
||||
if (color.a < alpha_reject) {
|
||||
discard;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
#version 430 core
|
||||
|
||||
layout (location = 0) in vec3 position_in;
|
||||
layout (location = 0) in vec4 position_in;
|
||||
layout (location = 1) in vec4 rgba_in;
|
||||
layout (location = 2) in vec3 tex_coord_in;
|
||||
|
||||
out vec4 fragment_color;
|
||||
out vec3 tex_coord;
|
||||
out float fog;
|
||||
|
||||
// putting all texture info stuff here so it's easier to copy-paste
|
||||
layout (location = 3) in uvec4 tex_info_in;
|
||||
|
@ -18,4 +19,5 @@ void main() {
|
|||
fragment_color = vec4(rgba_in.x, rgba_in.y, rgba_in.z, rgba_in.w * 2.);
|
||||
tex_coord = tex_coord_in;
|
||||
tex_info = tex_info_in;
|
||||
fog = position_in.w / 255.;
|
||||
}
|
||||
|
|
|
@ -4,10 +4,12 @@ out vec4 color;
|
|||
|
||||
in vec4 fragment_color;
|
||||
in vec3 tex_coord;
|
||||
in float fogginess;
|
||||
uniform sampler2D tex_T0;
|
||||
|
||||
uniform float alpha_min;
|
||||
uniform float alpha_max;
|
||||
uniform vec4 fog_color;
|
||||
|
||||
void main() {
|
||||
//vec4 T0 = texture(tex_T0, tex_coord);
|
||||
|
@ -21,4 +23,6 @@ void main() {
|
|||
if (color.a > alpha_max) {
|
||||
discard;
|
||||
}
|
||||
|
||||
color.xyz = mix(color.xyz, fog_color.xyz / 255., clamp(fogginess/255 * fog_color.w, 0., 1.));
|
||||
}
|
||||
|
|
|
@ -7,10 +7,13 @@ layout (location = 2) in int time_of_day_index;
|
|||
uniform vec4 hvdf_offset;
|
||||
uniform mat4 camera;
|
||||
uniform float fog_constant;
|
||||
uniform float fog_min;
|
||||
uniform float fog_max;
|
||||
layout (binding = 10) uniform sampler1D tex_T1; // note, sampled in the vertex shader on purpose.
|
||||
|
||||
out vec4 fragment_color;
|
||||
out vec3 tex_coord;
|
||||
out float fogginess;
|
||||
|
||||
void main() {
|
||||
|
||||
|
@ -38,6 +41,11 @@ void main() {
|
|||
// compute Q
|
||||
float Q = fog_constant / transformed[3];
|
||||
|
||||
float fog1 = -transformed.w + hvdf_offset.w;
|
||||
float fog2 = min(fog1, fog_max);
|
||||
float fog3 = max(fog2, fog_min);
|
||||
fogginess = 255 - fog3;
|
||||
|
||||
// perspective divide!
|
||||
transformed.xyz *= Q;
|
||||
|
||||
|
|
|
@ -119,7 +119,7 @@ void TFragment::render(DmaFollower& dma,
|
|||
m_tfrag3.setup_for_level(m_tree_kinds, level_name, render_state);
|
||||
TfragRenderSettings settings;
|
||||
settings.hvdf_offset = m_tfrag_data.hvdf_offset;
|
||||
settings.fog_x = m_tfrag_data.fog.x();
|
||||
settings.fog = m_tfrag_data.fog;
|
||||
memcpy(settings.math_camera.data(), &m_buffered_data[0].pad[TFragDataMem::TFragMatrix0 * 16],
|
||||
64);
|
||||
settings.tree_idx = 0;
|
||||
|
@ -175,7 +175,7 @@ void TFragment::render(DmaFollower& dma,
|
|||
m_many_level_render.tie_level_renderers[i]->setup_for_level(level_names[i], render_state);
|
||||
TfragRenderSettings settings;
|
||||
settings.hvdf_offset = m_tfrag_data.hvdf_offset;
|
||||
settings.fog_x = m_tfrag_data.fog.x();
|
||||
settings.fog = m_tfrag_data.fog;
|
||||
memcpy(settings.math_camera.data(),
|
||||
&m_buffered_data[0].pad[TFragDataMem::TFragMatrix0 * 16], 64);
|
||||
settings.tree_idx = 0;
|
||||
|
|
|
@ -499,7 +499,7 @@ void Tfrag3::render_tree_cull_debug(const TfragRenderSettings& settings,
|
|||
settings.hvdf_offset[3]);
|
||||
glUniform1f(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "fog_constant"),
|
||||
settings.fog_x);
|
||||
settings.fog.x());
|
||||
// glDisable(GL_DEPTH_TEST);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_GEQUAL);
|
||||
|
|
|
@ -411,7 +411,7 @@ void Tie3::render(DmaFollower& dma, SharedRenderState* render_state, ScopedProfi
|
|||
|
||||
TfragRenderSettings settings;
|
||||
settings.hvdf_offset = m_pc_port_data.hvdf_off;
|
||||
settings.fog_x = m_pc_port_data.fogx;
|
||||
settings.fog = m_pc_port_data.fog;
|
||||
|
||||
memcpy(settings.math_camera.data(), m_pc_port_data.camera[0].data(), 64);
|
||||
settings.tree_idx = 0;
|
||||
|
@ -703,7 +703,7 @@ void Tie3::render_tree(int idx,
|
|||
settings.hvdf_offset[3]);
|
||||
glUniform1f(
|
||||
glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3_NO_TEX].id(), "fog_constant"),
|
||||
settings.fog_x);
|
||||
settings.fog.x());
|
||||
glDisable(GL_BLEND);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDrawElements(GL_TRIANGLE_STRIP, draw_size, GL_UNSIGNED_INT, (void*)offset);
|
||||
|
|
|
@ -150,7 +150,14 @@ void first_tfrag_draw_setup(const TfragRenderSettings& settings, SharedRenderSta
|
|||
settings.hvdf_offset[0], settings.hvdf_offset[1], settings.hvdf_offset[2],
|
||||
settings.hvdf_offset[3]);
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_constant"),
|
||||
settings.fog_x);
|
||||
settings.fog.x());
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_min"),
|
||||
settings.fog.y());
|
||||
glUniform1f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_max"),
|
||||
settings.fog.z());
|
||||
glUniform4f(glGetUniformLocation(render_state->shaders[ShaderId::TFRAG3].id(), "fog_color"),
|
||||
render_state->fog_color[0], render_state->fog_color[1], render_state->fog_color[2],
|
||||
render_state->fog_intensity);
|
||||
}
|
||||
|
||||
void interp_time_of_day_slow(const float weights[8],
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
struct TfragRenderSettings {
|
||||
math::Matrix4f math_camera;
|
||||
math::Vector4f hvdf_offset;
|
||||
float fog_x;
|
||||
math::Vector4f fog;
|
||||
int tree_idx;
|
||||
float time_of_day_weights[8] = {0};
|
||||
math::Vector4f planes[4];
|
||||
|
@ -53,8 +53,7 @@ struct TfragPcPortData {
|
|||
math::Vector<s32, 4> itimes[4];
|
||||
math::Vector4f camera[4];
|
||||
math::Vector4f hvdf_off;
|
||||
float fogx;
|
||||
float unused[3];
|
||||
math::Vector4f fog;
|
||||
char level_name[12];
|
||||
u32 tree_idx;
|
||||
};
|
||||
|
|
|
@ -264,6 +264,7 @@ void render_game_frame(int width, int height, int lbox_width, int lbox_height) {
|
|||
options.draw_profiler_window = g_gfx_data->debug_gui.should_draw_profiler();
|
||||
options.playing_from_dump = false;
|
||||
options.save_screenshot = g_gfx_data->debug_gui.get_screenshot_flag();
|
||||
options.draw_small_profiler_window = g_gfx_data->debug_gui.small_profiler;
|
||||
if (options.save_screenshot) {
|
||||
options.screenshot_path = make_output_file_name(g_gfx_data->debug_gui.screenshot_name());
|
||||
}
|
||||
|
|
|
@ -345,6 +345,8 @@
|
|||
(set! (-> data-ptr 12) (-> *math-camera* hvdf-off quad))
|
||||
(let ((vec (-> (the (inline-array vector) data-ptr) 13)))
|
||||
(set! (-> vec x) (-> *math-camera* pfog0))
|
||||
(set! (-> vec y) (-> *math-camera* fog-min))
|
||||
(set! (-> vec z) (-> *math-camera* fog-max))
|
||||
)
|
||||
(charp<-string (the (pointer uint8) (&-> data-ptr 14)) (symbol->string (-> lev nickname)))
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue