HLSL Как можно передавать данные между шейдерами / читать существующее значение цвета?

Имею 2 шейдера HLSL ps2.0. В упрощенном виде это:

Шейдер 1

  • Читает текстуру
  • Выводит значение цвета на основе этой текстуры

Шейдер 2

  • Проблема: нужно прочитать цвет из шейдера 1
  • Выводит окончательный цвет, который является функцией входного цвета.

(Это должны быть разные шейдеры, так как я достиг максимальных выходов вершинных шейдеров для 1 шейдера)


Моя проблема в том, что я не могу понять, как Shader 2 может получить доступ к существующему цвету фрагмента / пикселя.

Знание того, как делать что-либо из этих вещей с помощью HLSL, решило бы мою проблему;

  • Считать существующий цвет пикселя (я не думаю, что это возможно)
  • Передать результат шейдера 1 в шейдер 2 как float4
  • Визуализируйте результат шейдера 1 как текстуру в памяти, и пусть шейдер 2 прочитает это в

person RJFalconer    schedule 11.05.2010    source источник
comment
См. Также developer.download.nvidia.com/shaderlibrary/webpages/ , материал обработка изображения рендеринг текстурированный   -  person RJFalconer    schedule 11.05.2010


Ответы (3)


Вариант 3:

Ваш HLSL-код будет простым, второй шейдер будет просто сэмплировать из texture2D и отменить его для своих вычислений.

Вам нужно будет отрисовать цель рендеринга с помощью вашего первого шейдера, затем вы можете привязать цель рендеринга к текстуре и получить к ней доступ из второго шейдера, как если бы это была любая другая текстура2D. Обратите внимание, что вы не можете читать из заданного в данный момент целевого объекта рендеринга, поэтому вернитесь к кадровому буферу перед вторым проходом.

Кроме того, не забудьте объяснить, как вам удалось достичь предела выходных данных вершинных шейдеров? Мне любопытно: P.

person Hannesh    schedule 22.11.2010

Чтобы делать то, что вы хотите, вы можете переключать цели рендеринга между исполнением shader1 и shader2. Вы выводите свой первый шейдер в текстуру, а затем передаете эту текстуру второму шейдеру.

Это делается в Ogre с помощью скриптов Compositor и цели.

person Julien Hoarau    schedule 11.05.2010
comment
Это именно то, чем я хочу заниматься, но я не могу найти информацию о том, как это сделать в сценариях HLSL и Ogre. Ссылка - OpenGL. - person RJFalconer; 11.05.2010
comment
Хорошо, поэтому я думаю, вам придется искать скрипты Ogre Compositor и target. (ogre3d.org/docs/manual/manual_29.html) - person Julien Hoarau; 11.05.2010
comment
Учебник Ogre по рендерингу в текстуру: ogre3d.org/wiki/index.php/Intermediate_Tutorial_7 - person Julien Hoarau; 11.05.2010

Скрипты Compositor, похоже, предназначены только для полноэкранных (или, точнее, полноэкранных) эффектов.

Рендеринг в текстуру - лучший способ. Это не обязательно достигается с помощью скриптов композитора.

Эта моя ветка на форумах Ogre идет более подробно;

   Ogre::Root r(...);
   Ogre::RenderWindow* window = r.createRenderWindow(...);
   //...
   Ogre::SceneManager* sm = r.createSceneManager(Ogre::ST_GENERIC, "sm");
   //...

   //Main scene camera
   Ogre::Camera* c = sm->createCamera("camera");
   {
       c->setNearClipDistance(5);
       Ogre::Viewport* v = window->addViewport(c);
       v->setBackgroundColour (Ogre::ColourValue(0, 0, 0));
       c->setAspectRatio (static_cast<double> (v->getActualWidth ()) / v->getActualHeight ());
   }

   //RTT
   Ogre::TexturePtr ptrTexture = Ogre::TextureManager::getSingleton().createManual(
       "RttTex",
       Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
       Ogre::TEX_TYPE_2D,
       512,//window->getWidth(),
       512,//window->getHeight(),
       0, //MIP_DEFAULT?
       Ogre::PF_R8G8B8,
       Ogre::TU_RENDERTARGET,
       0
   );
   Ogre::RenderTexture* renderTexture = ptrTexture->getBuffer()->getRenderTarget();
   renderTexture->setAutoUpdated(true);

   //Create material to use with rect
   {
       //You should replace this with the material you wish to render to texture
       //It can be defined in c++ (as this is) or in a material script
       Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().create("material", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
       Ogre::Technique* tech = material->createTechnique();
       tech->createPass();
       material->getTechnique(0)->getPass(0)->setLightingEnabled(false);
       material->getTechnique(0)->getPass(0)->setDepthCheckEnabled(false);
       material->getTechnique(0)->getPass(0)->createTextureUnitState("my_square_texture.dds");
   }

   //Create rect2D in yz plane to which we will draw our textures
   //Most likely you'll wish to reposition the node so it's offscreen
   const static float r_dimension = 1000.0;
   Ogre::SceneNode* rect_node = sm->getRootSceneNode()->createChildSceneNode("rect_node");
   {
       Ogre::ManualObject *rect = sm->createManualObject("rect");
       rect->begin("material", Ogre::RenderOperation::OT_TRIANGLE_FAN);
       rect->position(0, r_dimension, r_dimension);
       rect->textureCoord(0,0);
       rect->normal(0, 1, 0);
       rect->position(0, -r_dimension, r_dimension);
       rect->textureCoord(0,1);
       rect->normal(0, 1, 0);
       rect->position(0, -r_dimension, -r_dimension);
       rect->textureCoord(1,1);
       rect->normal(0, 1, 0);
       rect->position(0, r_dimension, -r_dimension);
       rect->textureCoord(1,0);
       rect->normal(0, 1, 0);
       rect->end();
       rect_node->attachObject(rect);
   }

   //Create camera, make it look at this rect2D
   Ogre::Camera* rtt_cam = sm->createCamera("rtt_cam");

   //Use same FOV as main camera
   Ogre::Radian fov_y = c->getFOVy();
   rtt_cam->setFOVy(fov_y);

   //Position the camera such that the texture fills the viewpoint
   {
       //Angle from normal (ie, "vector origin->camera") to to top of tecture is FOV/2
       //Distance origin to top of texture is r_dimension
       double cam_to_rect_distance = r_dimension/tan((fov_y.valueRadians())/2);
       rtt_cam->setPosition(cam_to_rect_distance, 0, 0);
       rtt_cam->lookAt(rect_node->getPosition());
   }

   //Debug using main window
   //window->addViewport(rtt_cam);

   //Write to RTT
   Ogre::Viewport* v = renderTexture->addViewport(rtt_cam);

   v->setClearEveryFrame(true); //You may wish to set this to false and render only when your material updates/changes
   v->setBackgroundColour(Ogre::ColourValue::Blue); //Debug colour. If we see blue border in RTT our cam position is wrong.
   v->setOverlaysEnabled(false); //We don't want overlays to show up on the RTT

   //TEMP Create debug screen (lifted from Ogre Tutorial 7)
   //Draws the result of RTT onscreen picture-in-picture
   {
       Ogre::Rectangle2D *miniScreen = new Ogre::Rectangle2D(true);
       miniScreen->setCorners(0.5f, -0.5f, 1.0f, -1.0f);
       //miniScreen->setBoundingBox(Ogre::AxisAlignedBox(-100000.0f * Ogre::Vector3::UNIT_SCALE, 100000.0f * Ogre::Vector3::UNIT_SCALE));
       Ogre::SceneNode* miniScreenNode = sm->getRootSceneNode()->createChildSceneNode("MiniScreenNode");
       miniScreenNode->attachObject(miniScreen);

       //Create material to read result of Rtt, purely for debug purposes
       Ogre::MaterialPtr screenMaterial = Ogre::MaterialManager::getSingleton().create("ScreenMatt", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
       Ogre::Technique* screenTechnique = screenMaterial->createTechnique();
       screenTechnique->createPass();
       screenMaterial->getTechnique(0)->getPass(0)->setLightingEnabled(false);
       screenMaterial->getTechnique(0)->getPass(0)->createTextureUnitState("RttTex");

       miniScreen->setMaterial("ScreenMatt");

       //TODO ideally we'd have render target listeners call setVisible(false) on pre update and  setVisible(true) post update,
       //so we don't get the infinite line picture-in-picture-in-picture in the preview window.
   }

   //Now you can bind your shader's material script to the rtt
{
    Ogre::MaterialPtr material = Ogre::MaterialManager::getSingleton().getByName("your_material_name");
    Ogre::Technique *technique = material->getTechnique(0);
    Ogre::Pass *pass = technique->getPass(0);
    Ogre::TextureUnitState *tunit = pass->getTextureUnitState("your_materials_tunit_name");
    tunit->setTextureName("Rtt");
}

   //...

   while (! window->isClosed ()) {
       //...
       r.renderOneFrame();
   }
person RJFalconer    schedule 18.11.2010