xmvlad
>+ class Material
>{
>public:
> virtual void setup_material(Static_Mesh_Render* static_mesh_render) = 0;
О ужас! Боже мой!
Теперь Cadaverillo решил, что асе - это для лохов, и заэкспортил md5, хочет скелетку и тот же detail на ней, что и на чайнике!
Не много ли менять?
MiF
Cadaverillo агрегирует общую функциональность(если она есть), в интерфейс - Shared_Material_Render и делает небольшой рефакторинг.
+ class Shared_Material_Render: public Render_Agent { public: void setup_detail_material(Detail_Material* detail_material); }; + class Static_Mesh_Render_D3D9: public Shared_Material_Render { public: void render_static_mesh( Static_Mesh_D3D9* static_mesh) { set matirces from camera and static mesh set vertex buffer set render state call drawprimitive + static_mesh->m_materal->setup_material( this); } }; + class Material { public: + virtual void setup_material( Shared_Material_Render* shared_material_render) = 0; }; + class Detail_Material: public Material { public: + void setup_material( Shared_Material_Render* shared_material_render) { shared_material_render->setup_detail_material( this); } } + class Sceleton_Render: public Shared_Material_Render { public: void render_sceleton( Sceleton_D3D9* sceleton) { set matirces from camera and static mesh set vertex buffer set render state call drawprimitive + sceleton->m_materal->setup_material( this); } }; + class Sceleton: public Scene_Object { public: void render( ) { m_sceleton_render->render_sceleton( this) } private: Sceleton_Render_D3D9* sceleton_render; };
xmvlad
>MiF
>Cadaverillo агрегирует общую функциональности(если она есть), в интерфейс -
>Shared_Material_Render и делает небольшой рефакторинг.
Cadaverillo не останавливается на достигнутом и всегда идет только вперед! Умные люди сказали ему, что нужно сортировать по мешам и материалам и он спешит это сделать!
2all
Основные минусы, о которых я говорил - лезут уже здесь. О runtime композиции можно сразу забыть. Compile-time композиция громоздка + требует регулярного рефакторинга
К посту 39 - и после этого говорится о расширяемости?
Захотели добавить detail текстуры - переделали интерфейс static_mesh плюс в каждой реализации дописали код.
Ну-ну.
Поддерживаю MiF, короче.
.
MiF
Cadaverillo, задумывается, как ему организовать сортировку, на базе Shared_Material_Render(однородная структура данных) или оставить данные у рендер агентов, сохранив информацию о типе. Очевидно, второй вариант больше ему подходит. Теперь при вызове render_agent->render, происходит лишь сбор данных, для "реального рендеринга" используется метод - sort_and_render_now. Для каждого материала и меша добавляет ID, по которому и будет сортировать
class Material { public: virtual void setup_material(Shared_Material_Render* shared_material_render) = 0; + Material_ID get_id( ); }; class Static_Mesh_Render_D3D9: public Shared_Material_Render { private: + struct Static_Mesh_Entry { Mesh_ID m_mesh_id; Material_ID m_material_id; Static_Mesh_D3D9* m_static_mesh; } + vector<Static_Mesh_Entry> static_mesh_data; public: + void render_static_mesh( Static_Mesh_D3D9* static_mesh) { Static_Mesh_Entry entry; entry.m_mesh_id = static_mesh->get_mesh_id( ); entry.m_material_id = static_mesh->get_material_id( ); entry.m_static_mesh = static_mesh; static_mesh_data.push_back( static_mesh); } + void sort_and_render_now( ) { // алгоритм расписывать не буду ибо тривиальный, сортируем по мешам, затем в каждой // подгруппе с эквивалентным Mesh_ID сортируем по Material_ID sort_mesh_and_material( static_mesh_data); // для каждой подгруппы мешей устанавливаем геометрию Static_Mesh_D3D9* current_static_mesh = static_mesh_data[i].static_mesh; set vertex buffer for current_static_mesh set index buffer for current_static_mesh // для каждой подгруппы материалов устанавливаем материал static_mesh->m_materal->setup_material( this); // для каждого объекта current_static_mesh->get_wordl_tm( ); current_static_mesh->get_locall_tm( ); set matirces from camera and static mesh set render state call drawprimitive } }; class Sceleton_Render_D3D9: public Shared_Material_Render { private: + struct Sceleton_Mesh_Entry { Mesh_ID m_mesh_id; Material_ID m_material_id; Sceleton* m_sceleton; } + vector<Sceleton_Entry> sceleton_data; public: + void render_static_mesh( Sceleton* sceleton) { Sceleton_Mesh_Entry entry; entry.m_mesh_id = sceleton->get_mesh_id( ); entry.m_material_id = sceleton->get_material_id( ); entry.m_static_mesh = sceleton; static_mesh_data.push_back( static_mesh); } + void sort_and_render_now( ) { // Если скелетка считается на ЦПУ, сортирует только по материалам sort_material( sceleton_data); // для каждой подгруппы мешей с одинаковым материалом, устанавливаем материал Sceleton_D3D9* current_sceleton = sceleton_data[i].sceleton; sceleton->m_materal->setup_material( this); // для каждого меша считаем скелетку на ЦПУ, загоняем в видеокарту current_static_mesh->get_wordl_tm( ); current_static_mesh->get_locall_tm( ); set matirces from camera and static mesh set render state call drawprimitive // Если скелетка считается на ГПУ сортируем так же как и в Static_Mesh, и просчитываем кости } }; class Static_Mesh: public Scene_Object { public: + void clone( Static_Mesh* static_mesh_clone); }; class Sceleton: public Scene_Object { public: + void clone( Scene_Object* sceleton_clone); };
Теперь он понимает, что нельзя изменять стейт объекта, после того как он отдан рендер агенту. Для каждого объекта вводит метод ->clone() - объект сам себя клонирует. (используется в рендер агенте для дублирования или руками, it depends)
PS: если вдруг находится какая-то общая функциональность выносится в Shared_Material_Render.
MiF
>Основные минусы, о которых я говорил - лезут уже здесь. О runtime композиции можно сразу забыть. Compile-time композиция
> громоздка + требует регулярного рефакторинга
ты можешт пальцем показать в эти минусы, а то как всегда пустые слова. :)
Zeux
блин, посмотри внимательно, после рефакторинга вся общая функциональность по материалам находится в Shared_Material_Render! То что происходит - это процесс итеративной разработки, поступает функциональность, затем она реализуется в архитектуре. И то что для добавления самого первого материал понадобился рефакторинг, совсем не значит, что он понадобится для следующего.
xmvlad
Теперь Cadaverillo хочет отражений, да чтобы на зеркале была детальная и общая текстура и она смешалась с отражением для получения грязной, запыленной поверхности
xmvlad
>ты можешт пальцем показать в эти минусы, а то как всегда пустые слова. :)
Пока пусть дизайн был в развитии, сейчас еще немного углубим и подтвердим сказанное
Cadaverillo реализует новый материал (RT - render target): RT_Material, новый объект RT_Camera, и рендер агент RT_Render,
Compound_Material - сборка нескольких материалов и Material_Mixer.
+ class RT_Material: public Material { void setup_material(Shared_Material_Render* shared_material_render) { shared_material_render->setup_rt_material( this); } }; + class RT_Camera: public Scene_Object { void render( ) { m_rt_render->render_rt( this) } RT_Material* m_binded_rt_material; Camera_Frustum m_camera_frustum; Camera_Matrices m_camera_matrices; RT_Render* m_rt_render; }; + class RT_Render: public Render_Agent { void render_rt( RT_Camera* rt_camera) { // отсекаем объекты по фрустуму vector<Scene_Object*> scene_objects = some_homogenius_culling_structure->cull_scene_objects( rt_camer->frustum); vector<Shared_Material_Render*> renders; renders->setup_rt( rt_camera->material); for each in scene_objects->render( ); for each in renders->sort_and_render_now( ); } }; + class Material_Mixer: public Shared_Material_Render { public: void setup_first_material( Material* m_first_material) { устанавливаем внутренние данные пропускаем первый материал через интерфейс миксера m_first_material->setup_material( this); сохраняем данные первого материала } void setup_second_material( Material* m_second_material) { устанавливаем внутренние данные пропускаем второй материал через интерфейс миксера m_second_material->setup_material( this); сохраняем данные второго материала } void do_mix( ) { TO MIF: как он будет это делать, меня не е..... , это твоя этопия не моя :))) } }; + class Compound_Material: public Material { void setup_material( Shared_Material_Render* shared_material_render) { m_material_mixer->setup_first_material( m_first_material); m_material_mixer->setup_second_material( m_second_material); m_material_mixer->do_mix( ); shared_material_render->setup_material_mixer( m_material_mixer); } void set_first_material( Material* first_material); void set_second_material( Material* second_material); Material* m_first_material; Material* m_second_material; Material_Mixer* m_material_mixer; }
Империя атакует и наносит сокрушительный удар, враг повержен и демаролизован окончательно! :)))
xmvlad
Напиши еще список классов, которые на этом этапе подверглись изменению. Только не говори, что это последний раз.
MiF
Shared_Material_Render, для добавления миксера и ВСЕ. ты вобще код смотришь? или лишь бы что-то возразить пишешь? :)
xmvlad
>Shared_Material_Render, для добавления миксера и ВСЕ. ты вобще код смотришь?
да смотрю, а теперь напиши список классов, зависимых от shared_material_render
>или лишь бы что-то возразить пишешь? :)
править старый код = зло и признак плохого дизайна, тем более, что от него почти все зависимо, тебе это не ясно?
Тема в архиве.