Несоответствия векторов инцидентов в RenderMan
Я работаю над переводом серии легких и поверхностных шейдеров из 3Delight в PRMan, и я обнаружил разницу между этими двумя, которую я не могу отработать. Кажется, что когда поверхностный шейдер оценивается на непрозрачность передачи из-за следа в легком шейдере, вектор падения I
в PRMan устанавливается на поверхность нормально.
В моем примере сцены над диском плавает полушарие. Дальний свет сверху проецирует отслеживаемые значения пропускания на поверхности позади них (немного назад для света, но это демо). Поверхность в полушарии отображается как сплошная, окрашенная своими нормалями при просмотре камерой, но с непрозрачностью направления падения при запросе на передачу.
Вот как я ожидаю, что это будет выглядеть, и что я получу от 3Delight:
Обратите внимание, что пол сплошной, почти чистый зеленый; цвет, который мы ожидаем, если угол падения вертикальный. Тем не менее, это то, что я получаю, когда рендерирую ту же самую сцену с PRMan:
Похоже, что проецирует нормали.
Я пытался получить значения через rayinfo
и вычисление нового I
, но все эти значения совпадают с тем, что I
на самом деле установлен в. Я также заметил расхождения с E
, но я не смог записать то, что устанавливается в PRMan.
Q: Как я могу получить вектор инцидента, который я ожидаю?
Содержание scene.rib
:
Display "falloff.tiff" "framebuffer" "rgba"
Projection "perspective" "fov" [17]
Format 400 400 1
ShadingRate 0.25
PixelSamples 3 3
# Move the camera
Translate 0 -0.65 10
Rotate 30 -1 0 0
Option "searchpath" "string shader" ".:&"
WorldBegin
LightSource "projector" "projector_light"
"point to" [0 -1 0]
Surface "matte"
TransformBegin
Rotate 90 1 0 0
Disk 0 1.25 360
TransformEnd
Surface "inspect_incident"
Attribute "visibility" "integer transmission" [1]
Attribute "shade" "string transmissionhitmode" "shader"
TransformBegin
Translate 0 1 0
Rotate -90 1 0 0
Sphere 1 0 1 360
TransformEnd
WorldEnd
Содержание projector.sl
:
light projector(
float intensity = 1;
color lightcolor = 1;
point from = point "shader" (0,0,0);
point to = point "shader" (0,0,1);
float maxdist = 1e12;
) {
uniform vector dir = normalize(to - from);
solar(dir, 0.0) {
Cl = intensity * lightcolor * (1 - transmission(Ps, Ps - dir * maxdist));
}
}
Содержание inspect_incident.sl
:
class inspect_incident() {
public void opacity(output color Oi) {
vector In = normalize(I);
Oi = color((In + 1) / 2);
}
public void surface(output color Ci, Oi) {
vector Nn = normalize(N);
Ci = color((Nn + 1) / 2);
Oi = 1;
}
}
1 ответ
Цитирование документации для спец. __computesOpacity
параметр поверхности шейдеров:
Значение 0 означает, что шейдер не вычисляет непрозрачность (т.е. Oi == Os). Это может быть использовано для отмены режима попадания передачи шейдера. Для таких шейдеров метод opacity() будет пропущен для лучей передачи.
Значение 1 означает, что шейдер действительно вычисляет непрозрачность. Такие шейдеры будут запускаться для оценки их непрозрачности для проходящих лучей. Этот результат может кэшироваться средством визуализации и, следовательно, должен быть независимым от представления.
Значение 2 означает, что шейдер вычисляет непрозрачность в зависимости от вида. Таким образом, рендер будет избегать непрозрачности кэширования для лучей передачи. Непрозрачность все еще кэшируется с целью управления продолжениями на рассеянном и зеркальном лучах, но тени, зависящие от вида, могут генерироваться с использованием areashadow() или transmission(). Для режима 2 метод opacity() должен зависеть только от зависимых от вида объектов в проверке для raytype == "translation".
И цитируя Брайана из Pixar:
Установите это
2
делать то, что вы хотите. То, что вы видите, это рендер работаетopacity
однажды с куполамиI
и кеширует это.