shader: Get all aggregate shader inputs (eg. lights) in one go

This means that p3d_LightSource[n] will be fetched once off the LightAttrib, written to the matrix cache, and then indexed into by the various ShaderMatSpec. This should be significantly more efficient, but the main aim is to prepare for a new binding system in the new shader pipeline

User structs are still an exception as of now
This commit is contained in:
rdb 2024-08-23 15:09:21 +02:00
parent 99225dfaef
commit cd68287b6a
5 changed files with 367 additions and 171 deletions

View File

@ -1156,32 +1156,23 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
_target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
// Material matrix contains AMBIENT, DIFFUSE, EMISSION, SPECULAR+SHININESS
if (target_material->is_off()) {
into[0].set(1, 1, 1, 1);
into[1].set(1, 1, 1, 1);
into[2].set(0, 0, 0, 0);
into[3].set(0, 0, 0, 0);
into[Shader::MA_ambient].set(1, 1, 1, 1);
into[Shader::MA_diffuse].set(1, 1, 1, 1);
into[Shader::MA_emission].set(0, 0, 0, 0);
into[Shader::MA_specular].set(0, 0, 0, 0);
into[Shader::MA_base_color].set(0, 0, 0, 0);
into[Shader::MA_metallic_ior_roughness].set(0, 0, 0, 1);
return;
}
Material *m = target_material->get_material();
LVecBase4 spc = m->get_specular();
spc[3] = m->get_shininess();
into[0] = LCAST(float, m->get_ambient());
into[1] = LCAST(float, m->get_diffuse());
into[2] = LCAST(float, m->get_emission());
into[3] = LCAST(float, spc);
return;
}
case Shader::SMO_attr_material2: {
const MaterialAttrib *target_material = (const MaterialAttrib *)
_target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
if (target_material->is_off()) {
into[0].set(0, 0, 0, 0);
into[1].set(0, 0, 0, 1);
return;
}
Material *m = target_material->get_material();
into[0] = LCAST(float, m->get_base_color());
into[1].set(m->get_metallic(), m->get_refractive_index(), 0, m->get_roughness());
into[Shader::MA_ambient] = LCAST(float, m->get_ambient());
into[Shader::MA_diffuse] = LCAST(float, m->get_diffuse());
into[Shader::MA_emission] = LCAST(float, m->get_emission());
into[Shader::MA_specular] = LCAST(float, spc);
into[Shader::MA_base_color] = LCAST(float, m->get_base_color());
into[Shader::MA_metallic_ior_roughness].set(m->get_metallic(), m->get_refractive_index(), 0, m->get_roughness());
return;
}
case Shader::SMO_attr_color: {
@ -1210,22 +1201,13 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
Fog *fog = target_fog->get_fog();
if (fog == nullptr) {
into[0].set(0, 1, 1, 1);
into[1].set(1, 1, 1, 1);
return;
}
PN_stdfloat start, end;
fog->get_linear_range(start, end);
into[0].set(fog->get_exp_density(), start, end, 1.0f / (end - start));
return;
}
case Shader::SMO_attr_fogcolor: {
const FogAttrib *target_fog = (const FogAttrib *)
_target_rs->get_attrib_def(FogAttrib::get_class_slot());
Fog *fog = target_fog->get_fog();
if (fog == nullptr) {
into[0].set(1, 1, 1, 1);
return;
}
into[0] = LCAST(float, fog->get_color());
into[1] = LCAST(float, fog->get_color());
return;
}
case Shader::SMO_alight_x: {
@ -1706,7 +1688,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
fetch_specified_member(np, name->get_basename(), into[0]);
return;
}
case Shader::SMO_light_source_i_vec_attrib: {
case Shader::SMO_light_source_i: {
const LightAttrib *target_light;
_target_rs->get_attrib_def(target_light);
@ -1718,17 +1700,17 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
for (i = 0; i < num_lights; ++i) {
NodePath light = target_light->get_on_light(i);
nassertv(!light.is_empty());
fetch_specified_member(light, name, into[i]);
fetch_specified_light(light, into);
into += Shader::LA_COUNT;
}
// Apply the default OpenGL lights otherwise.
// Special exception for light 0, which defaults to white.
if (i == 0) {
//FIXME: only the color attribute
into[0].set(1, 1, 1, 1);
++i;
}
for (; i < (size_t)count; ++i) {
fetch_specified_member(NodePath(), name, into[i]);
fetch_specified_light(NodePath(), into);
if (i == 0) {
into[Shader::LA_color].set(1, 1, 1, 1);
}
into += Shader::LA_COUNT;
}
return;
}
@ -1767,7 +1749,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name,
return;
}
case Shader::SMO_light_source_i_packed: {
// The light matrix contains COLOR, ATTENUATION, POSITION, VIEWVECTOR
// The light matrix contains COLOR, ATTENUATION, VIEWVECTOR, POSITION
const LightAttrib *target_light;
_target_rs->get_attrib_def(target_light);
@ -2126,6 +2108,111 @@ fetch_specified_member(const NodePath &np, CPT_InternalName attrib, LVecBase4f &
}
}
/**
* Given a NodePath passed into a shader input that is a structure, fetches
* the value for the given member.
*/
void GraphicsStateGuardian::
fetch_specified_light(const NodePath &np, LVecBase4f *into) {
PandaNode *node = nullptr;
if (!np.is_empty()) {
node = np.node();
}
if (node == nullptr) {
into[Shader::LA_color].set(0, 0, 0, 1);
into[Shader::LA_specular].set(0, 0, 0, 1);
into[Shader::LA_ambient].set(0, 0, 0, 1);
into[Shader::LA_diffuse].set(0, 0, 0, 1);
into[Shader::LA_position].set(0, 0, 1, 0);
into[Shader::LA_half_vector].set(0, 0, 1, 0);
into[Shader::LA_spot_direction].set(0, 0, -1, 0);
into[Shader::LA_spot_params].set(-1, 180, 0, 0);
into[Shader::LA_attenuation].set(1, 0, 0, 0);
*(LMatrix4f *)&into[Shader::LA_shadow_view_matrix] = LCAST(float, shadow_bias_mat);
} else {
Light *light = node->as_light();
nassertv(light != nullptr);
LVecBase4f color = LCAST(float, light->get_color());
into[Shader::LA_color] = color;
into[Shader::LA_specular] = LCAST(float, light->get_specular_color());
if (node->is_ambient_light()) {
into[Shader::LA_ambient] = color;
into[Shader::LA_diffuse].set(0, 0, 0, 1);
into[Shader::LA_position].set(0, 0, 0, 0);
into[Shader::LA_half_vector].set(0, 0, 0, 0);
into[Shader::LA_spot_direction].set(0, 0, 0, 0);
into[Shader::LA_spot_params].set(-1, 180, 0, 0);
} else {
into[Shader::LA_ambient].set(0, 0, 0, 1);
into[Shader::LA_diffuse] = color;
CPT(TransformState) net_transform =
np.get_transform(_scene_setup->get_scene_root().get_parent());
CPT(TransformState) transform =
_scene_setup->get_cs_world_transform()->compose(net_transform);
const LMatrix4 &light_mat = transform->get_mat();
LightLensNode *light;
DCAST_INTO_V(light, node);
Lens *lens = light->get_lens();
nassertv(lens != nullptr);
if (node->is_of_type(DirectionalLight::get_class_type())) {
DirectionalLight *light;
DCAST_INTO_V(light, node);
LVector3 dir = -(light->get_direction() * light_mat);
into[Shader::LA_position].set(dir[0], dir[1], dir[2], 0);
dir.normalize();
dir += LVector3(0, 0, 1);
dir.normalize();
into[Shader::LA_half_vector].set(dir[0], dir[1], dir[2], 1);
}
else {
LPoint3 pos = lens->get_nodal_point() * light_mat;
into[Shader::LA_position].set(pos[0], pos[1], pos[2], 1);
pos.normalize();
pos += LVector3(0, 0, 1);
pos.normalize();
into[Shader::LA_half_vector].set(pos[0], pos[1], pos[2], 1);
}
if (node->is_of_type(Spotlight::get_class_type())) {
float cutoff = lens->get_hfov() * 0.5f;
into[Shader::LA_spot_params].set(ccos(deg_2_rad(cutoff)), cutoff, light->get_exponent(), 0);
} else {
// spotCosCutoff, spotCutoff, spotExponent
into[Shader::LA_spot_params].set(-1, 180, light->get_exponent(), 0);
}
LVector3 dir = lens->get_view_vector() * light_mat;
into[Shader::LA_spot_direction].set(dir[0], dir[1], dir[2], 0);
LMatrix4 t = _inv_cs_transform->get_mat() *
_scene_setup->get_camera_transform()->get_mat() *
net_transform->get_inverse()->get_mat() *
LMatrix4::convert_mat(_coordinate_system, lens->get_coordinate_system());
if (!node->is_of_type(PointLight::get_class_type())) {
t *= lens->get_projection_mat() * shadow_bias_mat;
}
*(LMatrix4f *)&into[Shader::LA_shadow_view_matrix] = t;
}
LVecBase3 atten = light->get_attenuation();
PN_stdfloat radius = 0;
if (node->is_of_type(SphereLight::get_class_type())) {
radius = ((const SphereLight *)node)->get_radius();
}
into[Shader::LA_attenuation].set(atten[0], atten[1], atten[2], radius);
}
}
/**
* Like fetch_specified_value, but for texture inputs.
*/

View File

@ -343,6 +343,7 @@ public:
LVecBase4f *into, int count = 1);
void fetch_specified_member(const NodePath &np, CPT_InternalName member,
LVecBase4f &v);
void fetch_specified_light(const NodePath &np, LVecBase4f *into);
PT(Texture) fetch_specified_texture(Shader::ShaderTexSpec &spec,
SamplerState &sampler, int &view);
const Shader::ShaderPtrData *fetch_ptr_parameter(const Shader::ShaderPtrSpec& spec);

View File

@ -960,10 +960,11 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
}
bind._func = Shader::SMF_first;
bind._part[0] = Shader::SMO_apiview_to_apiclip_light_source_i;
bind._part[0] = Shader::SMO_light_source_i;
bind._arg[0] = nullptr;
bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr;
bind._offset = 4 * Shader::LA_shadow_view_matrix;
} else if (strncmp(name_buffer, "shadowMatrix", 127) == 0) {
// Only supported for backward compatibility: includes the model
@ -1074,90 +1075,88 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
GLCAT.error()
<< "p3d_Material.baseColor should be vec4\n";
}
bind._part[0] = Shader::SMO_attr_material2;
bind._offset = 4 * Shader::MA_base_color;
bind._piece = Shader::SMP_vec4;
_shader->cp_add_mat_spec(bind);
return;
} else if (noprefix == "Material.ambient") {
}
else if (noprefix == "Material.ambient") {
if (param_type != GL_FLOAT_VEC4) {
GLCAT.error()
<< "p3d_Material.ambient should be vec4\n";
}
bind._offset = 4 * Shader::MA_ambient;
bind._piece = Shader::SMP_vec4;
_shader->cp_add_mat_spec(bind);
return;
} else if (noprefix == "Material.diffuse") {
}
else if (noprefix == "Material.diffuse") {
if (param_type != GL_FLOAT_VEC4) {
GLCAT.error()
<< "p3d_Material.diffuse should be vec4\n";
}
bind._offset = 4 * Shader::MA_diffuse;
bind._piece = Shader::SMP_vec4;
bind._offset = 4;
_shader->cp_add_mat_spec(bind);
return;
} else if (noprefix == "Material.emission") {
}
else if (noprefix == "Material.emission") {
if (param_type != GL_FLOAT_VEC4) {
GLCAT.error()
<< "p3d_Material.emission should be vec4\n";
}
bind._offset = 4 * Shader::MA_emission;
bind._piece = Shader::SMP_vec4;
bind._offset = 8;
_shader->cp_add_mat_spec(bind);
return;
} else if (noprefix == "Material.specular") {
}
else if (noprefix == "Material.specular") {
if (param_type != GL_FLOAT_VEC3) {
GLCAT.error()
<< "p3d_Material.specular should be vec3\n";
}
bind._offset = 4 * Shader::MA_specular;
bind._piece = Shader::SMP_vec3;
bind._offset = 12;
_shader->cp_add_mat_spec(bind);
return;
} else if (noprefix == "Material.shininess") {
}
else if (noprefix == "Material.shininess") {
if (param_type != GL_FLOAT) {
GLCAT.error()
<< "p3d_Material.shininess should be float\n";
}
bind._offset = 4 * Shader::MA_specular + 3;
bind._piece = Shader::SMP_scalar;
bind._offset = 15;
_shader->cp_add_mat_spec(bind);
return;
} else if (noprefix == "Material.roughness") {
}
else if (noprefix == "Material.roughness") {
if (param_type != GL_FLOAT) {
GLCAT.error()
<< "p3d_Material.roughness should be float\n";
}
bind._part[0] = Shader::SMO_attr_material2;
bind._offset = 4 * Shader::MA_metallic_ior_roughness + 3;
bind._piece = Shader::SMP_scalar;
bind._offset = 7;
_shader->cp_add_mat_spec(bind);
return;
} else if (noprefix == "Material.metallic") {
}
else if (noprefix == "Material.metallic") {
if (param_type != GL_FLOAT && param_type != GL_BOOL) {
GLCAT.error()
<< "p3d_Material.metallic should be bool or float\n";
}
bind._part[0] = Shader::SMO_attr_material2;
bind._offset = 4 * Shader::MA_metallic_ior_roughness;
bind._piece = Shader::SMP_scalar;
bind._offset = 4;
_shader->cp_add_mat_spec(bind);
return;
} else if (noprefix == "Material.refractiveIndex") {
}
else if (noprefix == "Material.refractiveIndex") {
if (param_type != GL_FLOAT) {
GLCAT.error()
<< "p3d_Material.refractiveIndex should be float\n";
}
bind._part[0] = Shader::SMO_attr_material2;
bind._offset = 4 * Shader::MA_metallic_ior_roughness + 1;
bind._piece = Shader::SMP_scalar;
bind._offset = 5;
_shader->cp_add_mat_spec(bind);
return;
}
@ -1231,7 +1230,8 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._arg[1] = nullptr;
if (noprefix == "Fog.color") {
bind._part[0] = Shader::SMO_attr_fogcolor;
bind._part[0] = Shader::SMO_attr_fog;
bind._offset = 4 * Shader::FA_color;
if (param_type == GL_FLOAT_VEC3) {
bind._piece = Shader::SMP_vec3;
@ -1245,6 +1245,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} else if (noprefix == "Fog.density") {
bind._part[0] = Shader::SMO_attr_fog;
bind._offset = 4 * Shader::FA_params;
if (param_type == GL_FLOAT) {
bind._piece = Shader::SMP_scalar;
@ -1256,10 +1257,10 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} else if (noprefix == "Fog.start") {
bind._part[0] = Shader::SMO_attr_fog;
bind._offset = 4 * Shader::FA_params + 1;
if (param_type == GL_FLOAT) {
bind._piece = Shader::SMP_scalar;
bind._offset = 1;
} else {
GLCAT.error()
<< "p3d_Fog.start should be float\n";
@ -1268,10 +1269,10 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} else if (noprefix == "Fog.end") {
bind._part[0] = Shader::SMO_attr_fog;
bind._offset = 4 * Shader::FA_params + 2;
if (param_type == GL_FLOAT) {
bind._piece = Shader::SMP_scalar;
bind._offset = 2;
} else {
GLCAT.error()
<< "p3d_Fog.end should be float\n";
@ -1280,10 +1281,10 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
} else if (noprefix == "Fog.scale") {
bind._part[0] = Shader::SMO_attr_fog;
bind._offset = 4 * Shader::FA_params + 3;
if (param_type == GL_FLOAT) {
bind._piece = Shader::SMP_scalar;
bind._offset = 3;
} else {
GLCAT.error()
<< "p3d_Fog.scale should be float\n";
@ -1350,11 +1351,78 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
bind._id = arg_id;
bind._func = Shader::SMF_first;
bind._index = index;
bind._part[0] = Shader::SMO_light_source_i_vec_attrib;
bind._arg[0] = InternalName::make(member_name);
bind._part[0] = Shader::SMO_light_source_i;
bind._arg[0] = nullptr;
bind._part[1] = Shader::SMO_identity;
bind._arg[1] = nullptr;
GLenum expected = GL_FLOAT_VEC4;
if (member_name == "color") {
bind._offset = 4 * Shader::LA_color;
}
else if (member_name == "specular") {
bind._offset = 4 * Shader::LA_specular;
}
else if (member_name == "ambient") {
bind._offset = 4 * Shader::LA_ambient;
}
else if (member_name == "diffuse") {
bind._offset = 4 * Shader::LA_diffuse;
}
else if (member_name == "position") {
bind._offset = 4 * Shader::LA_position;
}
else if (member_name == "halfVector") {
bind._offset = 4 * Shader::LA_half_vector;
}
else if (member_name == "spotDirection") {
bind._offset = 4 * Shader::LA_spot_direction;
}
else if (member_name == "spotCosCutoff") {
bind._offset = 4 * Shader::LA_spot_params;
expected = GL_FLOAT;
}
else if (member_name == "spotCutoff") {
bind._offset = 4 * Shader::LA_spot_params + 1;
expected = GL_FLOAT;
}
else if (member_name == "spotExponent") {
bind._offset = 4 * Shader::LA_spot_params + 2;
expected = GL_FLOAT;
}
else if (member_name == "attenuation") {
bind._offset = 4 * Shader::LA_attenuation;
expected = GL_FLOAT_VEC3;
}
else if (member_name == "constantAttenuation") {
bind._offset = 4 * Shader::LA_attenuation;
expected = GL_FLOAT;
}
else if (member_name == "linearAttenuation") {
bind._offset = 4 * Shader::LA_attenuation + 1;
expected = GL_FLOAT;
}
else if (member_name == "quadraticAttenuation") {
bind._offset = 4 * Shader::LA_attenuation + 2;
expected = GL_FLOAT;
}
else if (member_name == "radius") {
bind._offset = 4 * Shader::LA_attenuation + 3;
expected = GL_FLOAT;
}
else {
GLCAT.error()
<< "Invalid light struct member " << member_name << "\n";
return;
}
// It's okay to declare as vec3 if we allow vec4.
if (param_type != expected && (expected != GL_FLOAT_VEC4 || param_type != GL_FLOAT_VEC3)) {
GLCAT.error()
<< "p3d_LightSource[]." << member_name << " has unexpected type\n";
return;
}
switch (param_type) {
case GL_FLOAT:
bind._piece = Shader::SMP_scalar;
@ -1373,8 +1441,7 @@ reflect_uniform(int i, char *name_buffer, GLsizei name_buflen) {
break;
default:
GLCAT.error()
<< "p3d_LightSource[]." << member_name << " should be float or vec\n";
assert(false);
return;
}
_shader->cp_add_mat_spec(bind);

View File

@ -381,16 +381,16 @@ cp_dependency(ShaderMatInput inp) {
if (inp == SMO_INVALID) {
return SSD_NONE;
}
if (inp == SMO_attr_material || inp == SMO_attr_material2) {
if (inp == SMO_attr_material) {
dep |= SSD_material | SSD_frame;
}
if (inp == SMO_attr_color || inp == SMO_attr_material2) {
if (inp == SMO_attr_color) {
dep |= SSD_color;
}
if (inp == SMO_attr_colorscale) {
dep |= SSD_colorscale;
}
if (inp == SMO_attr_fog || inp == SMO_attr_fogcolor) {
if (inp == SMO_attr_fog) {
dep |= SSD_fog | SSD_frame;
}
if ((inp == SMO_model_to_view) ||
@ -459,12 +459,12 @@ cp_dependency(ShaderMatInput inp) {
}
}
if ((inp == SMO_light_ambient) ||
(inp == SMO_light_source_i_vec_attrib) ||
(inp == SMO_light_source_i) ||
(inp == SMO_apiview_to_apiclip_light_source_i) ||
(inp == SMO_light_source_i_packed)) {
dep |= SSD_light | SSD_frame;
}
if (inp == SMO_light_source_i_vec_attrib ||
if (inp == SMO_light_source_i ||
inp == SMO_apiview_to_apiclip_light_source_i ||
inp == SMO_light_source_i_packed ||
inp == SMO_mat_constant_x_attrib ||
@ -512,6 +512,90 @@ cp_dependency(ShaderMatInput inp) {
return dep;
}
/**
* Given ShaderMatInput, returns the size in the cache that this part requires.
*/
int Shader::
cp_size(ShaderMatInput inp) {
switch (inp) {
case SMO_INVALID:
return 0;
case SMO_window_size:
case SMO_pixel_size:
case SMO_texpad_x:
case SMO_texpix_x:
case SMO_attr_color:
case SMO_attr_colorscale:
case SMO_satten_x:
case SMO_plane_x:
case SMO_clipplane_x:
case SMO_vec_constant_x:
case SMO_frame_number:
case SMO_frame_time:
case SMO_frame_delta:
case SMO_vec_constant_x_attrib:
case SMO_light_ambient:
case SMO_light_product_i_ambient:
case SMO_light_product_i_diffuse:
case SMO_light_product_i_specular:
case SMO_apiview_clipplane_i:
case SMO_tex_is_alpha_i:
case SMO_texscale_i:
case SMO_texcolor_i:
case SMO_texconst_i:
case SMO_attr_pointparams:
return 1;
case SMO_identity:
case SMO_alight_x:
case SMO_dlight_x:
case SMO_plight_x:
case SMO_slight_x:
case SMO_texmat_i:
case SMO_mat_constant_x:
case SMO_world_to_view:
case SMO_view_to_world:
case SMO_model_to_view:
case SMO_view_to_model:
case SMO_apiview_to_view:
case SMO_view_to_apiview:
case SMO_clip_to_view:
case SMO_view_to_clip:
case SMO_apiclip_to_view:
case SMO_view_to_apiclip:
case SMO_view_x_to_view:
case SMO_view_to_view_x:
case SMO_apiview_x_to_view:
case SMO_view_to_apiview_x:
case SMO_clip_x_to_view:
case SMO_view_to_clip_x:
case SMO_apiclip_x_to_view:
case SMO_view_to_apiclip_x:
case SMO_mat_constant_x_attrib:
case SMO_apiview_to_apiclip_light_source_i:
case SMO_model_to_apiview:
case SMO_apiview_to_model:
case SMO_apiview_to_apiclip:
case SMO_apiclip_to_apiview:
case SMO_inv_texmat_i:
case SMO_light_source_i_packed:
return 4;
case SMO_attr_material:
return MA_COUNT;
case SMO_light_source_i:
return LA_COUNT;
case SMO_attr_fog:
return FA_COUNT;
}
nassertr(false, 0);
return 0;
}
/**
* Adds the given ShaderMatSpec to the shader's mat spec table.
*/
@ -581,7 +665,7 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
for (int i = 0; i < 2; ++i) {
if (spec._part[i] == SMO_texmat_i ||
spec._part[i] == SMO_inv_texmat_i ||
spec._part[i] == SMO_light_source_i_vec_attrib ||
spec._part[i] == SMO_light_source_i ||
spec._part[i] == SMO_apiview_to_apiclip_light_source_i ||
spec._part[i] == SMO_light_product_i_ambient ||
spec._part[i] == SMO_light_product_i_diffuse ||
@ -638,6 +722,7 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
}
offset += part._count * part._size;
}
int size = cp_size(spec._part[p]);
if (i == _mat_parts.size()) {
// Didn't find this part yet, create a new one.
ShaderMatPart part;
@ -645,83 +730,7 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
part._count = end[p];
part._arg = spec._arg[p];
part._dep = dep;
switch (part._part) {
case SMO_INVALID:
part._size = 0;
break;
case SMO_window_size:
case SMO_pixel_size:
case SMO_texpad_x:
case SMO_texpix_x:
case SMO_attr_color:
case SMO_attr_colorscale:
case SMO_satten_x:
case SMO_plane_x:
case SMO_clipplane_x:
case SMO_vec_constant_x:
case SMO_attr_fog:
case SMO_attr_fogcolor:
case SMO_frame_number:
case SMO_frame_time:
case SMO_frame_delta:
case SMO_vec_constant_x_attrib:
case SMO_light_ambient:
case SMO_light_source_i_vec_attrib:
case SMO_light_product_i_ambient:
case SMO_light_product_i_diffuse:
case SMO_light_product_i_specular:
case SMO_apiview_clipplane_i:
case SMO_tex_is_alpha_i:
case SMO_texscale_i:
case SMO_texcolor_i:
case SMO_texconst_i:
case SMO_attr_pointparams:
part._size = 1;
break;
case SMO_attr_material2:
part._size = 2;
break;
case SMO_identity:
case SMO_attr_material:
case SMO_alight_x:
case SMO_dlight_x:
case SMO_plight_x:
case SMO_slight_x:
case SMO_texmat_i:
case SMO_mat_constant_x:
case SMO_world_to_view:
case SMO_view_to_world:
case SMO_model_to_view:
case SMO_view_to_model:
case SMO_apiview_to_view:
case SMO_view_to_apiview:
case SMO_clip_to_view:
case SMO_view_to_clip:
case SMO_apiclip_to_view:
case SMO_view_to_apiclip:
case SMO_view_x_to_view:
case SMO_view_to_view_x:
case SMO_apiview_x_to_view:
case SMO_view_to_apiview_x:
case SMO_clip_x_to_view:
case SMO_view_to_clip_x:
case SMO_apiclip_x_to_view:
case SMO_view_to_apiclip_x:
case SMO_mat_constant_x_attrib:
case SMO_apiview_to_apiclip_light_source_i:
case SMO_model_to_apiview:
case SMO_apiview_to_model:
case SMO_apiview_to_apiclip:
case SMO_apiclip_to_apiview:
case SMO_inv_texmat_i:
case SMO_light_source_i_packed:
part._size = 4;
break;
}
part._size = size;
if (spec._func != SMF_first) {
assert(part._size == 4);
@ -730,7 +739,7 @@ cp_add_mat_spec(ShaderMatSpec &spec) {
_mat_cache_deps |= part._dep;
_mat_parts.push_back(std::move(part));
}
spec._cache_offset[p] = offset + begin[p];
spec._cache_offset[p] = offset + begin[p] * size;
}
if (spec._func == SMF_shader_input_ptr) {
_mat_scratch_size = std::max(_mat_scratch_size, spec._array_count);
@ -1188,6 +1197,7 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._arg[0] = nullptr;
bind._part[1] = SMO_identity;
bind._arg[1] = nullptr;
bind._offset = FA_params;
} else if (pieces[1] == "fogcolor") {
if (!cp_errchk_parameter_float(p,3,4)) {
return false;
@ -1195,10 +1205,11 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._id = p._id;
bind._piece = SMP_vec4;
bind._func = SMF_first;
bind._part[0] = SMO_attr_fogcolor;
bind._part[0] = SMO_attr_fog;
bind._arg[0] = nullptr;
bind._part[1] = SMO_identity;
bind._arg[1] = nullptr;
bind._offset = FA_color;
} else if (pieces[1] == "ambient") {
if (!cp_errchk_parameter_float(p,3,4)) {
return false;
@ -1229,11 +1240,12 @@ compile_parameter(ShaderArgInfo &p, int *arg_dim) {
bind._id = p._id;
bind._piece = SMP_vec4;
bind._func = SMF_first;
bind._part[0] = SMO_light_source_i_vec_attrib;
bind._arg[0] = InternalName::make("specular");
bind._part[0] = SMO_light_source_i;
bind._arg[0] = nullptr;
bind._part[1] = SMO_identity;
bind._arg[1] = nullptr;
bind._index = atoi(pieces[1].c_str() + 5);
bind._offset = LA_specular;
} else if (pieces[1] == "pointparams") {
if (!cp_errchk_parameter_float(p,3,4)) {
return false;

View File

@ -173,7 +173,6 @@ public:
SMO_view_to_apiclip_x,
SMO_attr_fog,
SMO_attr_fogcolor,
SMO_frame_number,
SMO_frame_time,
@ -183,7 +182,8 @@ public:
SMO_vec_constant_x_attrib,
SMO_light_ambient,
SMO_light_source_i_vec_attrib,
SMO_light_source_i,
SMO_light_source_i_packed,
SMO_apiview_to_apiclip_light_source_i,
SMO_light_product_i_ambient,
@ -200,14 +200,9 @@ public:
SMO_inv_texmat_i,
// Additional properties for PBR materials
SMO_attr_material2,
// Hack for text rendering. Don't use in user shaders.
SMO_tex_is_alpha_i,
SMO_light_source_i_packed,
// Texture scale component of texture matrix.
SMO_texscale_i,
@ -358,6 +353,39 @@ public:
SPT_unknown
};
// Attributes (vec4) of the material structure.
enum MaterialAttribute {
MA_ambient,
MA_diffuse,
MA_emission,
MA_specular, // shininess in w
MA_base_color,
MA_metallic_ior_roughness,
MA_COUNT,
};
// Attributes (vec4) of the light structure.
enum LightAttribute {
LA_color,
LA_specular,
LA_ambient,
LA_diffuse,
LA_position,
LA_half_vector,
LA_spot_direction,
LA_spot_params, // spotCosCutoff, spotCutoff, spotExponent
LA_attenuation, // and radius
LA_shadow_view_matrix, // mat4
LA_COUNT = LA_shadow_view_matrix + 4,
};
// Attributes (vec4) of the fog structure.
enum FogAttribute {
FA_params, // exp density, start, end, scale
FA_color,
FA_COUNT,
};
struct ShaderArgInfo {
ShaderArgId _id;
ShaderArgClass _class;
@ -550,6 +578,7 @@ public:
vector_string &pieces, int &next,
ShaderMatSpec &spec, bool fromflag);
int cp_dependency(ShaderMatInput inp);
int cp_size(ShaderMatInput inp);
void cp_add_mat_spec(ShaderMatSpec &spec);
size_t cp_get_mat_cache_size() const;
size_t cp_get_mat_scratch_size() const;