HLSL Как можно пройти данные между шейдерами / чтением существующего цвета цвета?
-
25-09-2019 - |
Вопрос
У меня есть 2 шейдеры HLSL PS2.0. Упрощенные, они:
Шейдер 1.
- Читает текстуру
- Выводит значение цвета на основе этой текстуры
Шейдер 2.
- Проблема: надо читать в цвете из Shader 1
- Выводит последний цвет, который является функцией входного цвета
(Они должны быть разными шейдерами, поскольку я добрался до максимального выхода вершин-шейдеров для 1 шейдера)
Моя проблема в том, что я не могу выработать, как Shader 2 может получить доступ к существующему цвету фрагмента / пикселя.
Зная, как сделать любую из этих вещей с HLSL, решит мою проблему;
- Читайте существующий пиксельный цвет (я не думаю, что это возможно)
- Пройти результат шейдера 1 в шейдер 2 как float4
- Визуализация результата шейдера 1 как текстура в памяти, и у шейдера 2 прочтете это в
Решение 3
Сценарии композиторов, кажется, только для полноэкранных (или более точно, полной точки зрения) эффектов.
Визуализация - к текстуре - это путь. Это не обязательно достигнуто с помощью сценариев композиторов.
Эта тема моего на форумах Огре уходит более подробно;
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();
}
Другие советы
Вариант 3:
Ваш код HLSL будет прост, второй шейдер будет просто образец из текстуры2d и und, что для его расчетов.
Вам нужно будет нарисовать до визуализация цели С вашим первым шейдером вы можете связать свою целевую цену на текстуру и получить доступ к нему из второго шейдера, как если бы это была какая-либо другая текстура2d. Обратите внимание, что вы не можете прочитать из целей рендеринга, который в настоящее время устанавливается, установлен обратно в кадрбафтер до вашего второго прохода.
Также, заботиться, чтобы объяснить, как вам удалось достичь предела на выходах вершин Мне любопытно: с.
Делать то, что вы хотите, вы можете переключать цели рендеринга между выполнением Shader1 и Shader2. Вы выводите свой первый шейдер на текстуру, а затем вы передаете эту текстуру своему второму шейдеру.
Это делается в огре с Сценарии композиторов и цель.