diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 55863d42fb..b2683dcdbe 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -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. */ diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index 78d06f4551..711ab5d74e 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -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); diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index fcf2837348..5ed9c1ff37 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -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); diff --git a/panda/src/gobj/shader.cxx b/panda/src/gobj/shader.cxx index 286543aba8..eca73217b6 100644 --- a/panda/src/gobj/shader.cxx +++ b/panda/src/gobj/shader.cxx @@ -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; diff --git a/panda/src/gobj/shader.h b/panda/src/gobj/shader.h index 196ede0980..4bd548d331 100644 --- a/panda/src/gobj/shader.h +++ b/panda/src/gobj/shader.h @@ -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;