Смешивание различных Program3D приводит к тому, что некоторые объекты не отображаются

Я столкнулся с чем-то неожиданным, работая с Stage3D. Я сделал две разные шейдерные программы для своих объектов. Одна из программ предназначена для использования текстурированных растровых изображений и ультрафиолетовых данных. Другой просто использует данные о цвете. Эти два объекта сильно различаются, потому что в конечном итоге я буду отображать некоторые вещи (например, линии направления, блики и т. Д.), Используя сплошные цвета и простую логику рендеринга, в то время как другие вещи (например, реальные объекты, фон и т. Д.) Будут отображаться с помощью mipmaps и т. Д. вперед. Проблема в том, что когда я использую эти две совершенно разные шейдерные программы, работает только одна или другая. Так что или все мои объекты только для цвета появляются или все мои объекты только для текстуры появляются. Очевидно, я хочу, чтобы оба появились.

Вот мой код для текстурированных объектов:

вершинный шейдер:

//4x4 matrix multiply to get camera angle
"m44 op, va0, vc0\n" + 
//tell fragment shader about xyz
"mov v0, va0\n" + 
//tell frament shader about uv
"mov v1, va1\n" + 
//tell fragment shader about RGBA
"mov v2, va2\n"

фрагментный шейдер:

//grab the texture color from texture 0 and
//the uv coordinates from varying register 1 and
//store the interpolated value in ft0
"tex ft0, v1, fs0 <2d,linear,repeat,miplinear>\n" + 
//move this value to the output color
"mov oc, ft0\n"

Код рендеринга для этих объектов выглядит следующим образом:

context3D.setProgram(_renderProgram);
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, renderMatrix, true);
context3D.setTextureAt(0, texture);

// vertex position to attribute register 0
context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
context3D.setVertexBufferAt(1, uvBuffer, 0, Context3DVertexBufferFormat.FLOAT_2);
context3D.setVertexBufferAt(2, colorsBuffer, 0, Context3DVertexBufferFormat.FLOAT_4);

Вот мой код agal для однотонных объектов (т.е. без текстуры):

вершинный шейдер:

"m44 op, va0, vc0\n" + // pos to clipspace
"mov v0, va1" // copy color

фрагментный шейдер:

"mov oc, v0 "

Код рендеринга для этих объектов выглядит следующим образом:

context3D.setProgram(_renderProgram); 
context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, renderMatrix, true);
// vertex position to attribute register 0
context3D.setVertexBufferAt(0, vertexBuffer, 0, Context3DVertexBufferFormat.FLOAT_3);
// color to attribute register 1
context3D.setVertexBufferAt(1, vertexBuffer, 3, Context3DVertexBufferFormat.FLOAT_3);

По какой-то причине, которую я не могу понять, тот факт, что я назначаю разные данные разным различным индексам регистров (va), приводит к сбою одной из процедур рендеринга. Если я сначала рендерим текстурный объект в моем цикле текстуры, все мои цветные объекты исчезают, и наоборот. Объекты будут отображаться правильно для самого первого кадра. Но как только цикл рендеринга воспроизводится во второй раз, происходит это неожиданное поведение.

Я обнаружил, что если я изменю код рендеринга цветового объекта, добавив следующее:

context3D.setTextureAt(0, null);
context3D.setVertexBufferAt(2, null);

Оно работает. Но это действительно не очень хорошее решение. Я не хочу знать, что где-то в моей программе другой объект рендерит с n изменяющимися регистрами, поэтому, если другому экземпляру program3D нужно меньше n, я должен установить все эти неиспользуемые va равными нулю. Кроме того, если я создаю новую шейдерную программу для какого-либо объекта (например, светящегося объекта), которому теперь требуется 4-й элемент va, теперь мне нужно вернуться и изменить все остальные мои программы шейдеров, чтобы установить для va4 значение null, чтобы все отображалось. Это по-настоящему? Конечно, я что-то здесь упускаю. То же самое касается установки всех моих текстурных регистров (футов).

Я могу предоставить гораздо больше информации...

2 ответа

К сожалению, похоже, что вы правы - по крайней мере, это было решение, которое я нашел и реализовал. Ранее пропущенные текстуры должны быть "очищены"...

context3D.setTextureAt(<n>, null);

... в противном случае ваш шейдер без текстур все равно будет ожидать текстуру и не будет визуализироваться.

Выкопать старый пост здесь. Я заметил ваши комментарии и подумал, что упомяну (в основном для будущих читателей), что на самом деле вы наткнулись на правильное решение. При подготовке к рисованию 3D-объекта на экране типичный процесс выглядит следующим образом:

  • определить / скомпилировать / загрузить программу
  • загрузить вершины и текстуры
  • начать цикл рендеринга
    • начать цикл объекта
      • установить программу
      • установить константы
      • установить входные буферы и текстуры
      • вызовите drawTriangles()
      • установить входные буферы и текстуры на ноль
    • цикл конца объекта
    • вызовите подарок ()
  • конец цикла рендеринга
Другие вопросы по тегам