ShaderGenerator: Add support for perspective points

Fixes #1440
This commit is contained in:
rdb 2023-01-13 19:12:01 +01:00
parent 6ad50b5cb1
commit 709555577f
7 changed files with 85 additions and 6 deletions

View File

@ -57,6 +57,7 @@
#include "colorScaleAttrib.h"
#include "clipPlaneAttrib.h"
#include "fogAttrib.h"
#include "renderModeAttrib.h"
#include "config_pstatclient.h"
#include <limits.h>
@ -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();

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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 {

View File

@ -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 InternalName *, const char *>::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();

View File

@ -151,6 +151,7 @@ protected:
bool _lighting;
bool _have_separate_ambient;
// Also contains bit 0x10000 indicating perspective point mode
int _fog_mode;
int _outputs;