From 709555577f638b9ee6d18c1e860e0827b427ac66 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 13 Jan 2023 19:12:01 +0100 Subject: [PATCH] ShaderGenerator: Add support for perspective points Fixes #1440 --- panda/src/display/graphicsStateGuardian.cxx | 28 +++++++++++++++++ panda/src/glstuff/glCgShaderContext_src.cxx | 4 +++ panda/src/glstuff/glShaderContext_src.cxx | 5 +++ panda/src/gobj/shader.cxx | 14 +++++++++ panda/src/gobj/shader.h | 4 +++ panda/src/pgraphnodes/shaderGenerator.cxx | 35 +++++++++++++++++---- panda/src/pgraphnodes/shaderGenerator.h | 1 + 7 files changed, 85 insertions(+), 6 deletions(-) diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index b06e520fd3..1a39fd4ca6 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -57,6 +57,7 @@ #include "colorScaleAttrib.h" #include "clipPlaneAttrib.h" #include "fogAttrib.h" +#include "renderModeAttrib.h" #include "config_pstatclient.h" #include @@ -1508,6 +1509,33 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, } return &t; } + case Shader::SMO_attr_pointparams: { + const RenderModeAttrib *target_render_mode; + _target_rs->get_attrib_def(target_render_mode); + + PN_stdfloat thickness = target_render_mode->get_thickness(); + PN_stdfloat catten = thickness; + PN_stdfloat patten = 0.0f; + if (target_render_mode->get_perspective()) { + LVecBase2i pixel_size = _current_display_region->get_pixel_size(); + + LVector3 height(0.0f, thickness, 1.0f); + height = height * _projection_mat->get_mat(); + height = height * _internal_transform->get_scale()[1]; + PN_stdfloat s = height[1] * pixel_size[1]; + + if (_current_lens->is_orthographic()) { + catten = s; + patten = 0.0f; + } else { + catten = 0.0f; + patten = s; + } + } + + t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, thickness, catten, patten, 0.0f); + return &t; + } default: nassertr(false /*should never get here*/, &LMatrix4::ident_mat()); return &LMatrix4::ident_mat(); diff --git a/panda/src/glstuff/glCgShaderContext_src.cxx b/panda/src/glstuff/glCgShaderContext_src.cxx index 5d2886cf39..fdfe2f2902 100644 --- a/panda/src/glstuff/glCgShaderContext_src.cxx +++ b/panda/src/glstuff/glCgShaderContext_src.cxx @@ -487,6 +487,10 @@ set_state_and_transform(const RenderState *target_rs, target_rs->get_attrib(TexGenAttrib::get_class_slot())) { altered |= Shader::SSD_tex_gen; } + if (state_rs->get_attrib(RenderModeAttrib::get_class_slot()) != + target_rs->get_attrib(RenderModeAttrib::get_class_slot())) { + altered |= Shader::SSD_render_mode; + } _state_rs = target_rs; } diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 44a22b8c71..34d6c1a706 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -25,6 +25,7 @@ #include "fogAttrib.h" #include "lightAttrib.h" #include "clipPlaneAttrib.h" +#include "renderModeAttrib.h" #include "bamCache.h" using std::dec; @@ -2135,6 +2136,10 @@ set_state_and_transform(const RenderState *target_rs, target_rs->get_attrib(TexGenAttrib::get_class_slot())) { altered |= Shader::SSD_tex_gen; } + if (state_rs->get_attrib(RenderModeAttrib::get_class_slot()) != + target_rs->get_attrib(RenderModeAttrib::get_class_slot())) { + altered |= Shader::SSD_render_mode; + } _state_rs = target_rs; } diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 95235ba5a8..6e911dfd5e 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -497,6 +497,9 @@ cp_dependency(ShaderMatInput inp) { if (inp == SMO_texconst_i) { dep |= SSD_tex_gen; } + if (inp == SMO_attr_pointparams) { + dep |= SSD_render_mode | SSD_transform | SSD_frame; + } return dep; } @@ -1039,6 +1042,17 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) { bind._part[1] = SMO_identity; bind._arg[1] = nullptr; bind._index = atoi(pieces[1].c_str() + 5); + } else if (pieces[1] == "pointparams") { + if (!cp_errchk_parameter_float(p,3,4)) { + return false; + } + bind._id = p._id; + bind._piece = SMP_row3; + bind._func = SMF_first; + bind._part[0] = SMO_attr_pointparams; + bind._arg[0] = nullptr; + bind._part[1] = SMO_identity; + bind._arg[1] = nullptr; } else { cp_report_error(p,"Unknown attr parameter."); return false; diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index 3dc9777b26..ef7d6ceef4 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -217,6 +217,9 @@ public: // Constant value of the TexGenAttrib of stage i. SMO_texconst_i, + // Point parameters + SMO_attr_pointparams, + SMO_INVALID }; @@ -325,6 +328,7 @@ public: SSD_texture = 0x1000, SSD_view_transform= 0x2000, SSD_tex_gen = 0x4000, + SSD_render_mode = 0x8000, }; enum ShaderBug { diff --git a/panda/src/pgraphnodes/shaderGenerator.cxx b/panda/src/pgraphnodes/shaderGenerator.cxx index 6fd05e35e3..5c9acef6d4 100644 --- a/panda/src/pgraphnodes/shaderGenerator.cxx +++ b/panda/src/pgraphnodes/shaderGenerator.cxx @@ -38,6 +38,7 @@ #include "texture.h" #include "ambientLight.h" #include "directionalLight.h" +#include "renderModeAttrib.h" #include "rescaleNormalAttrib.h" #include "pointLight.h" #include "sphereLight.h" @@ -567,6 +568,12 @@ analyze_renderstate(ShaderKey &key, const RenderState *rs) { if (rs->get_attrib(fog) && !fog->is_off()) { key._fog_mode = (int)fog->get_fog()->get_mode() + 1; } + + // Hijack this field for the perspective render-mode flag. + const RenderModeAttrib *render_mode; + if (rs->get_attrib(render_mode) && render_mode->get_perspective()) { + key._fog_mode |= 0x10000; + } } /** @@ -754,6 +761,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { bool need_eye_position = key._lighting; bool need_eye_normal = !key._lights.empty() || ((key._outputs & AuxBitplaneAttrib::ABO_aux_normal) != 0); bool need_tangents = ((key._texture_flags & ShaderKey::TF_map_normal) != 0); + bool need_point_size = (key._fog_mode & 0x10000) != 0; // If we have binormal/tangent and eye position, we can pack eye normal in // the w channels of the others. @@ -877,7 +885,8 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { text << "\t uniform float4x4 trans_model_to_view,\n"; eye_position_freg = alloc_freg(); text << "\t out float4 l_eye_position : " << eye_position_freg << ",\n"; - } else if (need_tangents) { + } + else if (need_tangents || need_point_size) { text << "\t uniform float4x4 trans_model_to_view,\n"; } if (need_eye_normal) { @@ -894,7 +903,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { text << "\t uniform float4 mspos_view,\n"; text << "\t out float3 l_eyevec,\n"; } - if (key._fog_mode != 0) { + if ((key._fog_mode & 0xffff) != 0) { hpos_freg = alloc_freg(); text << "\t out float4 l_hpos : " << hpos_freg << ",\n"; } @@ -934,6 +943,10 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { text << "\t in uint4 vtx_transform_index : " << transform_index_vreg << ",\n"; } } + if (need_point_size) { + text << "\t uniform float3 attr_pointparams,\n"; + text << "\t out float l_point_size : PSIZE,\n"; + } text << "\t in float4 vtx_position : " << position_vreg << ",\n"; text << "\t out float4 l_position : POSITION,\n"; text << "\t uniform float4x4 mat_modelproj\n"; @@ -965,7 +978,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { } text << "\t l_position = mul(mat_modelproj, vtx_position);\n"; - if (key._fog_mode != 0) { + if ((key._fog_mode & 0xffff) != 0) { text << "\t l_hpos = l_position;\n"; } if (need_world_position) { @@ -977,6 +990,13 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { if (need_eye_position) { text << "\t l_eye_position = mul(trans_model_to_view, vtx_position);\n"; } + else if (need_point_size) { + text << "\t float4 l_eye_position = mul(trans_model_to_view, vtx_position);\n"; + } + if (need_point_size) { + text << "\t l_point_size = attr_pointparams.y + attr_pointparams.z / length(l_eye_position.xyz);\n"; + } + pmap::const_iterator it; for (it = texcoord_fregs.begin(); it != texcoord_fregs.end(); ++it) { // Pass through all texcoord inputs as-is. @@ -1022,7 +1042,7 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { // Fragment shader text << "void fshader(\n"; - if (key._fog_mode != 0) { + if ((key._fog_mode & 0xffff) != 0) { text << "\t in float4 l_hpos : " << hpos_freg << ",\n"; text << "\t in uniform float4 attr_fog,\n"; text << "\t in uniform float4 attr_fogcolor,\n"; @@ -1717,8 +1737,8 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { } // Apply fog. - if (key._fog_mode != 0) { - Fog::Mode fog_mode = (Fog::Mode)(key._fog_mode - 1); + if ((key._fog_mode & 0xffff) != 0) { + Fog::Mode fog_mode = (Fog::Mode)((key._fog_mode & 0xffff) - 1); switch (fog_mode) { case Fog::M_linear: text << "\t result.rgb = lerp(attr_fogcolor.rgb, result.rgb, saturate((attr_fog.z - l_hpos.z) * attr_fog.w));\n"; @@ -1759,6 +1779,9 @@ synthesize_shader(const RenderState *rs, const GeomVertexAnimationSpec &anim) { if (key._disable_alpha_write) { shattr = DCAST(ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_disable_alpha_write, true); } + if (need_point_size) { + shattr = DCAST(ShaderAttrib, shattr)->set_flag(ShaderAttrib::F_shader_point_size, true); + } reset_register_allocator(); diff --git a/panda/src/pgraphnodes/shaderGenerator.h b/panda/src/pgraphnodes/shaderGenerator.h index dd5b3456c5..749f25a35d 100644 --- a/panda/src/pgraphnodes/shaderGenerator.h +++ b/panda/src/pgraphnodes/shaderGenerator.h @@ -151,6 +151,7 @@ protected: bool _lighting; bool _have_separate_ambient; + // Also contains bit 0x10000 indicating perspective point mode int _fog_mode; int _outputs;