Тут для солидных тел не могут толком трассировку наладить, а ты на полупрозрачные замахнулся, очуметь можно.
Добавлено 24-11-2019 в 19:23:
Довольно сложная штука этот макро-язык получается. Но по другому никак, ведь мы фактически задаём все юниформы и текстурные юниты из скрипта, тут не выйдет отделаться упрощённой формой записи - полезут разные нехорошие ограничения. А писать каждый раз полное выражение очень утомительно. Так что макро-замена тут идеальный выход. Это всё работает по принципу один раз настроил и больше не лазишь. Надо - еще добавил.
Добавлено 24-11-2019 в 19:26:
Сам макро-язык включает в себя три ключевых слова.
enum - это для макросчетчиков, которые можно инкременировать прямо во время макроподстановки, например для слоёв ландшафта или стадий в кутришном шейдере.
#keydef - заменяет одно регулярное выражение на другое. Пример:
C++ Source Code:
#keydef map <value>\
image u_ColorMap<unitNum> = "<value>";
второй аргумент - исходная переменная, путь к текстуре. А вот пример строгого соответствия
C++ Source Code:
#keydef map $lightmap\
image u_LightMap = "entity->$LightmapTexture";
Естественно, что у строгого соответствия приоритет выше.
ну и #define - заменяет одно слово на другое, без хитростей.
В принципе этого должно хватить, чтобы описать любую макроподстановку. Ну посмотрим.
Добавлено 24-11-2019 в 19:29:
А, да. <unitNum> в данном примере это как раз ссылка на счётчик, которая заменится на его текущее значение и получится строчка u_ColorMap0
Ну, разумеется к любой строке макро-подстановки это можно применять.
Сформированная финальная строка замены, просто подаётся на вход парсера, как будто бы она была в реальном файле и дальше парсинг происходит в обычном режиме.
Добавлено 24-11-2019 в 19:33:
И кстати это же правило действует на внутренние фигурные скобки, их тоже можно (и нужно) заменять.
У моей системы есть одно принципиальное ограничение - базовый формат, всегда должен иметь вид, типа
C++ Source Code:
materialName
{
}
Но для параноевских материалов и для кутришных шейдеров и для ку2-шных материалов из q2world и для дуумтришных материалов это требование соблюдается. Да и скорее всего еще много где, просто потому что это наиболее очевидный формат записи чего-либо. И вот эту конструкцию уже переопределить нельзя. Но не думаю, что это будет проблемой.
#define в моём языке всегда задаёт строгое соответствие замены A на B или A на пустоту. Сишная фишка с функциями типа #define func(a,b,c) не поддерживается, поскольку в подавляющем большинстве материалов никаких функций просто нет, там именно keyvalue pair. И наоборот, у меня работает то, что нереализуемо на сишных макросах (но там это и не нужно).
Простой пример, для кутришного блендфунка. Шаблон автозамены
blendFunc <src> <dst>
превращается сперва в
vec2 u_BlendFunc<unitNum> = vec2( <src>, <dst> );
потом подставляется текущее значение энума <unitNum>, а потом система ищет переопределение GL_SRC_XXX, GL_DST_XXX и тоже их заменяет на цифры. То есть финальный результат автозамены будет выглядеть примерно так:
C++ Source Code:
vec2 u_BlendFunc2 = vec2( 6.0, 8.0 );
и уже этот результат снова подаётся на вход парсера, где и читается в обычном режиме, т.к. нативный формат записи. А в шейдере для blendFunc будут условия на выходные значения, соответствующие режимам смещевания (собсно так и переводят кутришные шейдеры на GLSL). Для каждого юнита, соответственно юниформ со своим номером.
А чтобы понять, какие юниты задействованы в шейдере, у нас есть команда addShaderDefine( SHADER_STAGE<stageNumber> );
где stageNumber точно так же превратится в текущее значение счётчика.
Ну разумеется, в шейдере эти #ifdef SHADER_STAGE0, #ifdef SHADER_STAGE1 придётся прописывать ручками, но нам понадобится один-единственный шейдер для описания абсолютно всех комбинаций кутришных материалов.
thambs
Заранее скомпиленные шейдеры вроде только в OpenGL 4.5 и новее поддерживаются. Обычно-то их компилят-линкуют-подключают при инициализации рендерера.
каждый запуск читается налету, но это быстро. Это ж простая макро-подстановка и парсится она один раз при запуске движка.
Цитата:
nemyax писал: Заранее скомпиленные шейдеры вроде только в OpenGL 4.5 и новее поддерживаются
так это вообще не шейдеры. Скомпиленные шейдеры у меня тоже поддерживаются.
Добавлено 25-11-2019 в 18:07:
Так, ну чтожы, я сделал макроподстановки для большинства случаев, ну покрайней мере чтобы материалы Edge Of Forever ни на что не ругались.
Теперь самое сложное - надо написать такой шейдер, который бы всё это корректно учитывал. То что я распарсил - это же просто параметры на вход шейдера, конвертация.
Добавлено 25-11-2019 в 18:09:
Для интерисующихся, пример тепичного шейдера. сконверченного в мою систему:
C++ Source Code:
1
textures/moteof/walltrim2
2
{
3
<ShaderState>
4
addShaderDefine( SHADER_STAGE0 )
5
addShaderDefine( SHADER_STAGE1 )
6
u_ColorMap0:-1 = *unused*;
7
u_ColorMap1:-1 = *unused*;
8
vec2 u_BlendFunc2;
9
}
диффузка + лайтмапа. Не пугайтесь странным значениям, это у меня дебаг-инфо недоделатый.
Добавлено 25-11-2019 в 18:10:
А вот шейдер с множеством стадий
C++ Source Code:
1
textures/moteof/water_healing
2
{
3
<ShaderState>
4
addShaderDefine( APPLY_DEFORM_VERTS0 )
5
addShaderDefine( SHADER_STAGE0 )
6
addShaderDefine( APPLY_VERTEXCOLOR0 )
7
addShaderDefine( APPLY_COLORWAVE0 )
8
addShaderDefine( APPLY_TEXMOD_TRANSFORM0_0 )
9
addShaderDefine( APPLY_TEXMOD_TURB0_1 )
10
addShaderDefine( SHADER_STAGE1 )
11
addShaderDefine( APPLY_VERTEXCOLOR1 )
12
addShaderDefine( APPLY_COLORWAVE1 )
13
addShaderDefine( APPLY_TEXMOD_STRETCH1_0 )
14
addShaderDefine( APPLY_TEXMOD_SCROLL1_1 )
15
addShaderDefine( SHADER_STAGE2 )
16
addShaderDefine( APPLY_VERTEXCOLOR2 )
17
addShaderDefine( APPLY_COLORWAVE2 )
18
addShaderDefine( APPLY_TEXMOD_TURB2_0 )
19
addShaderDefine( SHADER_STAGE3 )
20
addShaderDefine( APPLY_VERTEXCOLOR3 )
21
addShaderDefine( APPLY_TEXMOD_STRETCH3_0 )
22
addShaderDefine( APPLY_TEXMOD_TRANSFORM3_1 )
23
addShaderDefine( APPLY_TEXMOD_ROTATE3_2 )
24
u_ColorMap0:-1 = *unused*;
25
u_ColorMap1:-1 = *unused*;
26
u_ColorMap2:-1 = *unused*;
27
u_ColorMap3:-1 = *unused*;
28
vec2 u_WaveDeformFunc0;
29
vec4 u_WaveDeformBase0;
30
vec2 u_BlendFunc1;
31
float u_rgbGenWaveFunc0;
32
vec4 u_rgbGenWaveParams0;
33
vec4 u_texModBase0_0;
34
vec2 u_texModTrans0_0;
35
vec4 u_texModTurb0_1;
36
vec2 u_BlendFunc2;
37
float u_rgbGenWaveFunc1;
38
vec4 u_rgbGenWaveParams1;
39
float u_texModWaveFunc1_0;
40
vec4 u_texModWaveParams1_0;
41
vec2 u_texModScroll1_1;
42
vec2 u_BlendFunc3;
43
float u_rgbGenWaveFunc2;
44
vec4 u_rgbGenWaveParams2;
45
vec4 u_texModTurb2_0;
46
vec2 u_BlendFunc4;
47
float u_texModWaveFunc3_0;
48
vec4 u_texModWaveParams3_0;
49
vec4 u_texModBase3_1;
50
vec2 u_texModTrans3_1;
51
float u_texModRotate3_2;
52
}
Впрочем старая проблема по прежнему остается - я так и не придумал как делать анимацию текстур. Но на этой карте её и нету.
Добавлено 25-11-2019 в 22:02:
Кстати, что касается времени такого парсинга с заменой. Оптимизировал функцию, теперь это занимает 0.3 секунды для полного пака кутришных шейдеров + еще шейдеров 500 от Сока для его карт и шейдеры для rustgrad.
Можно их еще хэшировать, но я думаю и так уже норм.
Выглядит очень переусложнённо в сравнении с самими ку3шными скриптами.
Да, возможностей больше - но они никому и не нужны. Сам же всем рассказывал, что мигающие лампочки нужны только Жэке в моде, а остальным достаточно статичных диффузки и нормалки.
XaeroX писал: Выглядит очень переусложнённо в сравнении с самими ку3шными скриптами.
то что я привёл - это скрытый промежуточный результат, который не виден пользователю. Это то, что подается на вход GLSL-шейдера. Ты правильно подметил, что это руками набивать - очуметь можно. А когда этим автозамена занимается - нормально.
Цитата:
XaeroX писал: Да, возможностей больше - но они никому и не нужны
Смысл в том, что пользователь сможет создать свой мета-язык для описания материалов. Кутришные шейдеры в данном случае это стресс-тест для проверки возможностей системы. Так-то я планирую еще описать тепичные параноевские материалы, только теперь их значения будут не захардкодены, а тоже описаны в скрипте.
Добавлено 26-11-2019 в 10:53:
Кстати и волатиловские шейдеры я смогу описать точно так же
Т.е. это мета-язык для описания рендеринга, который вмещает в себя большинство форматов, когда-либо придуманных для этого дела.