At this moment my application used for tests of compositor chains modiffication.
OffscreenParticles.cpp
Code: Select all
/*
-----------------------------------------------------------------------------
Filename: OffScreenParticles.cpp
-----------------------------------------------------------------------------
*/
#include "OffScreenParticles.h"
#include <OgreMath.h>
#include <OgreVector4.h>
#include <OgreColourValue.h>
#include <OgreSubEntity.h>
Ogre::Viewport* mViewport;
Ogre::SceneNode* headNode;
Ogre::SceneNode* barrelsNode;
Ogre::SceneNode* launcherNode;
Ogre::SceneNode* penguinTravelPathNode;
Ogre::SceneNode* penguinNode;
Ogre::SceneNode* fogNode;
Ogre::SceneNode* houseNode;
unsigned long period = 3000;
float headStartingPhase = 1.5f;
float barrelsPhaseDelay = 0.60f;
float headAmplitude = 30.0f;
float headAverageAngle = 2.5f;
float barrelsAmplitude = 25.0f;
float barrelsAverageAngle = 0.0f;
float previousPenguinHeigth = 0.0f;
float previousPenguinHeigthDelta = 0.0f;
float previousTravelAngle = 0.0f;
float previousPenguinAngle = 0.0f;
float previousHeadAngle = headStartingPhase*Ogre::Math::PI;
float previousBarrelsAngle = previousHeadAngle - barrelsPhaseDelay*Ogre::Math::PI;
float penguinAngle;
float headAngle;
float barrelsAngle;
int pushUpsBetweenTravelling = 5;
int loopsPerTravelling = 2;
unsigned int pushUpsCount = 0;
bool isPenguinTravelling=false;
//-------------------------------------------------------------------------------------
OffScreenParticles::OffScreenParticles(void)
{
}
//-------------------------------------------------------------------------------------
OffScreenParticles::~OffScreenParticles(void)
{
}
Ogre::String GetShaderFileNameSuffix(){
Ogre::String shaderFileNameSuffix;
// Use GLSL ES in case of OpenGL ES 2 render system.
if (Ogre::Root::getSingletonPtr()->getRenderSystem()->getName().find("OpenGL ES 2") != Ogre::String::npos)
{
shaderFileNameSuffix = "glsles";
}
// Use GLSL in case of OpenGL render system.
else if (Ogre::Root::getSingletonPtr()->getRenderSystem()->getName().find("OpenGL") != Ogre::String::npos)
{
shaderFileNameSuffix = "glsl";
}
// Use HLSL, Multiple Render Target in case of D3D9 render system.
else if (Ogre::Root::getSingletonPtr()->getRenderSystem()->getName().find("Direct3D9") != Ogre::String::npos)
{
shaderFileNameSuffix = "hlsl";
}
// Use HLSL, in case of D3D10 or D3D11 render system.
else if (Ogre::Root::getSingletonPtr()->getRenderSystem()->getName().find("Direct3D1") != Ogre::String::npos)
{
shaderFileNameSuffix = "hlsl4";
}
// If none of above render systems fit, use cg
else{
shaderFileNameSuffix = "cg";
}
return shaderFileNameSuffix;
}
bool OffScreenParticles::frameRenderingQueued(const Ogre::FrameEvent& evt)
{
float headPhase = mRoot->getTimer()->getMilliseconds() * Ogre::Math::PI / period + headStartingPhase*Ogre::Math::TWO_PI;
float barrelsPhase = headPhase - barrelsPhaseDelay*Ogre::Math::PI;
headAngle = (Ogre::Math::Sin(headPhase)) * headAmplitude + headAverageAngle;
barrelsAngle = (Ogre::Math::Sin(barrelsPhase)) * barrelsAmplitude + barrelsAverageAngle;
headNode->pitch(Ogre::Degree(headAngle-previousHeadAngle));
barrelsNode->pitch(Ogre::Degree(barrelsAngle-previousBarrelsAngle));
float penguinHeigth = (sin(mRoot->getTimer()->getMilliseconds() / 500.0)+1.0f) * 50.0f;
penguinNode->setPosition(0.0f, penguinHeigth, 0.0f);
float penguinHeigthDelta = penguinHeigth - previousPenguinHeigth;
if(!isPenguinTravelling){
float penguinRocketOscilation = mRoot->getTimer()->getMilliseconds() / 270.0;
// spin the head around and make it float up and down
launcherNode->setPosition(sin(penguinRocketOscilation) * 10.0f - 50.0f, 0.0f, -100.0f);
penguinAngle = -cos(penguinRocketOscilation) * 10.0f;
penguinNode->roll(Ogre::Degree(penguinAngle-previousPenguinAngle));
//checking if penguin has made next push-up
if(previousPenguinHeigthDelta>=0 && penguinHeigthDelta<0){
pushUpsCount = (pushUpsCount+1) % pushUpsBetweenTravelling;
if(pushUpsCount==0){
/*start travelling*/
isPenguinTravelling = true;
launcherNode->pitch(Ogre::Degree(30));
}
}
previousPenguinHeigth = penguinHeigth;
previousPenguinHeigthDelta = penguinHeigthDelta;
previousPenguinAngle = penguinAngle;
}
else{
float angleDelta = evt.timeSinceLastFrame*50;
//checking if penguin has made a loop;
if(previousTravelAngle + angleDelta > 360*loopsPerTravelling){
isPenguinTravelling = false;
angleDelta = 360*loopsPerTravelling - previousTravelAngle;
launcherNode->pitch(Ogre::Degree(-30));
previousTravelAngle = 0.0f;
}
else{
previousTravelAngle += angleDelta;
}
penguinTravelPathNode->yaw(Ogre::Degree(angleDelta));
}
previousHeadAngle = headAngle;
previousBarrelsAngle = barrelsAngle;
fogNode->yaw(Ogre::Degree(evt.timeSinceLastFrame * 200));
return BaseApplication::frameRenderingQueued(evt);
}
/*void BloomCompositorListener::notifyCompositor( Ogre::CompositorInstance * instance )
{
CompositorListener::notifyCompositor( instance );
// Get some RTT dimensions for later calculations
Ogre::CompositionTechnique::TextureDefinitionIterator defIter = instance->getTechnique()->getTextureDefinitionIterator();
while ( defIter.hasMoreElements() )
{
Ogre::CompositionTechnique::TextureDefinition * def = defIter.getNext();
if ( def->name == TTEXT("renderTarget1") || def->name == TTEXT("renderTarget2") )
{
def->width = mVpWidth / 2;
def->height = mVpHeight / 2;
}
}
}*/
enum ShaderParam { SP_SHININESS = 1, SP_DIFFUSE, SP_SPECULAR };
//-------------------------------------------------------------------------------------
void OffScreenParticles::createScene(void)
{
mViewport=mWindow->getViewport(0);
mViewport->setBackgroundColour(Ogre::ColourValue::ColourValue(0.2f,0.2f,0.2f,1));
Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "OSP_SolidMaterialsBuffer");
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "OSP_SolidMaterialsBuffer", true);
Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "OSP_ShowDepth");//"SSAO/Volumetric");//"SSAO/ShowNormals");
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "OSP_ShowDepth", true);//"SSAO/Volumetric", true);//"SSAO/ShowNormals", true);
Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "OSP_PostFilter");
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "OSP_PostFilter", true);
/*Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "Bloom");
Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "Bloom", true);*/
//Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "BlackWhite2");
//Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "BlackWhite2", true);
//Ogre::CompositorChain *chain = Ogre::CompositorManager::getSingleton().getCompositorChain(mViewport);
//Ogre::Compositor newCompositor = Ogre::CompositorManager::getSingleton().create("MyCompositor","MyGroup",true);
//Ogre::CompositionTechnique::TextureDefinitionIterator defIter = Ogre::CompositorManager::instance->get
mSceneMgr->setAmbientLight(Ogre::ColourValue(0.75f, 0.75f, 0.25f));
Ogre::Light* light = mSceneMgr->createLight("MainLight");
light->setPosition(200.0f, 80.0f, -50.0f);
// create your scene here :)
Ogre::SceneNode* root = mSceneMgr->getRootSceneNode();
//Ogre's head
headNode = root->createChildSceneNode("HeadNode");
Ogre::Entity* ogreHead = mSceneMgr->createEntity("Head", "ogrehead.mesh");
headNode->attachObject(ogreHead);
headNode->setPosition(50.0f, 0.0f, -100.0f);
headNode->pitch(Ogre::Degree(previousHeadAngle));
//ogreHead->setMaterialName("SSAO/ShowDepth");//"Examples/CelShading");
/*Ogre::SubEntity* sub;
sub = ogreHead->getSubEntity(0); // eyes
sub->setCustomParameter(SP_SHININESS, Ogre::Vector4(35, 0, 0, 0));
sub->setCustomParameter(SP_DIFFUSE, Ogre::Vector4(1, 0.3, 0.3, 1));
sub->setCustomParameter(SP_SPECULAR, Ogre::Vector4(1, 0.6, 0.6, 1));
sub = ogreHead->getSubEntity(1); // skin
sub->setCustomParameter(SP_SHININESS, Ogre::Vector4(10, 0, 0, 0));
sub->setCustomParameter(SP_DIFFUSE, Ogre::Vector4(0, 0.5, 0, 1));
sub->setCustomParameter(SP_SPECULAR, Ogre::Vector4(0.3, 0.5, 0.3, 1));
sub = ogreHead->getSubEntity(2); // earring
sub->setCustomParameter(SP_SHININESS, Ogre::Vector4(25, 0, 0, 0));
sub->setCustomParameter(SP_DIFFUSE, Ogre::Vector4(1, 1, 0, 1));
sub->setCustomParameter(SP_SPECULAR, Ogre::Vector4(1, 1, 0.7, 1));
sub = ogreHead->getSubEntity(3); // teeth
sub->setCustomParameter(SP_SHININESS, Ogre::Vector4(20, 0, 0, 0));
sub->setCustomParameter(SP_DIFFUSE, Ogre::Vector4(1, 1, 0.7, 1));
sub->setCustomParameter(SP_SPECULAR, Ogre::Vector4(1, 1, 1, 1));*/
//Barrels on Ogre's tusks
barrelsNode = headNode->createChildSceneNode("BarrelsNode");
barrelsNode->setPosition(0.0f, 5.0f, -2.0f);
barrelsNode->pitch(Ogre::Degree(previousBarrelsAngle));
//Right tusk Barrel
Ogre::SceneNode* barrel1Node = barrelsNode->createChildSceneNode("Barrel1Node");
Ogre::Entity* barrel1 = mSceneMgr->createEntity("Barrel1", "Barrel.mesh");
barrel1Node->attachObject(barrel1);
barrel1Node->setPosition(-21.0f, 2.0f, 0.0f);
barrel1Node->scale(1.25f, 1.25f, 1.25f);
//Right Barrel's smoke
Ogre::SceneNode* smoke1Node = barrel1Node->createChildSceneNode("Smoke1Node");
Ogre::ParticleSystem* smoke1 = mSceneMgr->createParticleSystem("Smoke1", "Examples/Smoke2");
//smoke1->setMaterialName("Examples/CelShading");
smoke1Node->attachObject(smoke1);
//Left tusk Barrel
Ogre::SceneNode* barrel2Node = barrelsNode->createChildSceneNode("Barrel2Node");
Ogre::Entity* barrel2 = mSceneMgr->createEntity("Barrel2", "Barrel.mesh");
barrel2Node->attachObject(barrel2);
barrel2Node->setPosition(21.0f, 2.0f, 0.0f);
barrel2Node->scale(1.25f, 1.25f, 1.25f);
//Left Barrel's smoke
Ogre::SceneNode* smoke2Node = barrel2Node->createChildSceneNode("Smoke2Node");
Ogre::ParticleSystem* smoke2 = mSceneMgr->createParticleSystem("Smoke2", "Examples/Smoke2");
smoke2Node->attachObject(smoke2);
//Penguin Travel Path
penguinTravelPathNode = root->createChildSceneNode("PenguinTravelPath");
penguinTravelPathNode->setPosition(25.0f, 0.0f, -100.0f);
//Penguin Launcher
launcherNode = penguinTravelPathNode->createChildSceneNode("LauncherNode");
launcherNode->setPosition(-75.0f, 0.0f, 0.0f);
//Penguin Rocket
penguinNode = launcherNode->createChildSceneNode("PenguinNode");
Ogre::Entity* penguin = mSceneMgr->createEntity("Penguin","penguin.mesh");
//penguin->setMaterialName("shader/orange_"+GetShaderFileNameSuffix());//"shader/smooth_add");//"Examples/CelShading");//"shader/depth_cg");//"PlainTexture");//"TextureModColor");
penguinNode->attachObject(penguin);
penguinNode->setPosition(0.0f, 50.0f, 0.0f);
//Penguin Rocket's jet
Ogre::SceneNode* penguinJetNode = penguinNode->createChildSceneNode("PenguinJetNode");
Ogre::ParticleSystem* penguinJet = mSceneMgr->createParticleSystem("PenguinJet", "Examples/JetEngine1");
penguinJetNode->attachObject(penguinJet);
//Fog
fogNode = launcherNode->createChildSceneNode("FogNode");
Ogre::ParticleSystem* fog = mSceneMgr->createParticleSystem("Fog", "Examples/Fog");
fogNode->attachObject(fog);
//fog->setMaterialName("ShowDepth");//"TextureModColor");//"PlainTexture");
//Ogre::CompositorManager::getSingleton().addCompositor(mViewport, "SSAO/Post/CrossBilateralFilter");//"DOF");//"DeferredShading/ShowDepthSpecular");//"Sharpen Edges");//"B&W");
//Ogre::CompositorManager::getSingleton().setCompositorEnabled(mViewport, "SSAO/Post/CrossBilateralFilter", true);//"DOF", true);//"DeferredShading/ShowDepthSpecular", true);//"Sharpen Edges", true);//"B&W", true);
ogreHead->setMaterialName("OSP_SolidMaterialsBuffer");
barrel1->setMaterialName("OSP_SolidMaterialsBuffer");
barrel2->setMaterialName("OSP_SolidMaterialsBuffer");
penguin->setMaterialName("OSP_SolidMaterialsBuffer");
//smoke1->setMaterialName("SSAO/GBuffer");
//smoke2->setMaterialName("SSAO/GBuffer");
//penguinJet->setMaterialName("SSAO/GBuffer");
//fog->setMaterialName("SSAO/GBuffer");
}
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
int main(int argc, char *argv[])
#endif
{
// Create application object
OffScreenParticles app;
try {
app.go();
} catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
std::cerr << "An exception has occured: " <<
e.getFullDescription().c_str() << std::endl;
#endif
}
return 0;
}
#ifdef __cplusplus
}
#endif
OffScreenParticles.h
Code: Select all
/*
-----------------------------------------------------------------------------
Filename: OffScreenParticles.h
-----------------------------------------------------------------------------
*/
#ifndef __TutorialApplication_h_
#define __TutorialApplication_h_
#include "BaseApplication.h"
class OffScreenParticles : public BaseApplication
{
public:
OffScreenParticles(void);
virtual ~OffScreenParticles(void);
virtual bool frameRenderingQueued(const Ogre::FrameEvent& evt);
protected:
virtual void createScene(void);
};
#endif // #ifndef __OffScreenParticles_h_
Entities that are manually given material "OSP_SolidMaterialsBuffer" should be displayed as non-particle systems - rendered to
texture that is visible in one of following compositors.
It seems that under DirectX9, all materials that are not "OSP_SolidMaterialsBuffer" are excluded from rendering.
In OpenGL rendering system they are visible. Compositor somehow renders them.
I should do that the way it is done in deferred shading. It is a little bit complicated there. However i think that there is no other solution than listeners. The clearest explanation how to use them that i found till now is http://www.ogre3d.org/forums/viewtopic.php?f=5&t=67593 I'll try to solve it that way.
Depth together with other values is passed between compositors in mrt texture (like in compositor "SSAO/GBuffer" from example applications).
Code: Select all
texture mrt target_width target_height PF_FLOAT32_RGBA PF_FLOAT32_RGBA PF_FLOAT32_RGBA chain_scope
And this is understood as G-Buffer there.
I'm doing passing of texture with colour in RGB and depth in alpha channel.
Code: Select all
texture depthInAlpha target_width target_height PF_FLOAT32_RGBA chain_scope
Right now code of gbuffer looks like this:
OSP.compositor
Code: Select all
compositor OSP_SolidMaterialsBuffer
{
technique
{
texture depthInAlpha target_width target_height PF_FLOAT32_RGBA chain_scope
texture occlusion target_width target_height PF_FLOAT32_RGBA chain_scope
target depthInAlpha
{
input none
shadows off
pass clear
{
buffers colour depth stencil
depth_value 1.0
}
pass render_scene {}
}
}
}
This compositor aim is to check if depth is acquired correctly:
Code: Select all
compositor OSP_ShowDepth
{
technique
{
texture_ref occlusion OSP_SolidMaterialsBuffer occlusion
target occlusion
{
input none
pass render_quad
{
// Renders a fullscreen quad with a material
material OSP_ShowDepth
}
}
}
}
In this one today I'll modify texture maximum of depth downsample.
(For every field of 2x2 or 4x4 or 8x8 depth values, the maximum value will be chosen).
Right now it just displays everything without modiffication.
Code: Select all
compositor OSP_PostFilter
{
technique
{
target_output
{
input none
pass render_quad
{
material OSP_PostFilter
}
}
}
}
This is the file with materials used in this copositor chain.
OSP.material
Code: Select all
/*fragment_program OSP_ShowDepth_fp_hlsl hlsl
{
source OSP.cg
entry_point OSP_ShowDepth_fp
target ps_3_0
}*/
fragment_program OSP_ShowDepth_fp_cg cg
{
source OSP.cg
entry_point OSP_ShowDepth_fp
profiles ps_2_x arbfp1
}
fragment_program OSP_ShowDepth_fp unified
{
//delegate OSP_ShowDepth_fp_hlsl
delegate OSP_ShowDepth_fp_cg
}
material OSP_ShowDepth
{
technique
{
pass
{
depth_check off
vertex_program_ref Ogre/Compositor/StdQuad_vp {}
fragment_program_ref OSP_ShowDepth_fp {}
texture_unit
{
content_type compositor OSP_SolidMaterialsBuffer depthInAlpha
tex_address_mode clamp
filtering none
}
texture_unit
{
texture gray256.png
tex_address_mode wrap
filtering none
}
}
}
}
//---------------------------------------------------
// Gbuffer Material
/*vertex_program OSP_SolidMaterialsBuffer_vp_hlsl hlsl
{
source OSP.cg
entry_point OSP_SolidMaterialsBuffer_vp
target vs_3_0
}
fragment_program OSP_SolidMaterialsBuffer_fp_hlsl hlsl
{
source OSP.cg
entry_point OSP_SolidMaterialsBuffer_fp
target ps_3_0
}*/
vertex_program OSP_SolidMaterialsBuffer_vp_cg cg
{
source OSP.cg
entry_point OSP_SolidMaterialsBuffer_vp
profiles vs_2_x arbvp1
default_params
{
}
}
fragment_program OSP_SolidMaterialsBuffer_fp_cg cg
{
source OSP.cg
entry_point OSP_SolidMaterialsBuffer_fp
profiles ps_3_0 arbfp1
default_params
{
}
}
vertex_program OSP_SolidMaterialsBuffer_vp unified
{
//delegate OSP_SolidMaterialsBuffer_vp_hlsl
delegate OSP_SolidMaterialsBuffer_vp_cg
}
fragment_program OSP_SolidMaterialsBuffer_fp unified
{
//delegate OSP_SolidMaterialsBuffer_fp_hlsl
delegate OSP_SolidMaterialsBuffer_fp_cg
}
material OSP_SolidMaterialsBuffer
{
technique
{
pass
{
//scene_blend alpha_blend
vertex_program_ref OSP_SolidMaterialsBuffer_vp
{
param_named_auto worldViewProj worldviewproj_matrix
param_named_auto texelOffsets texel_offsets
param_named_auto depthRange scene_depth_range
}
fragment_program_ref OSP_SolidMaterialsBuffer_fp
{
param_named_auto depthRange scene_depth_range
}
texture_unit
{
texture Ten.png 2d
}
}
}
}
//------------------------------------------------
/*fragment_program OSP_PostFilter_fp_hlsl hlsl
{
source OSP.cg
entry_point OSP_PostFilter_fp
target ps_3_0
}*/
fragment_program OSP_PostFilter_fp_cg cg
{
source OSP.cg
entry_point OSP_PostFilter_fp
profiles ps_3_0 ps_2_x arbfp1
}
fragment_program OSP_PostFilter_fp unified
{
// delegate OSP_PostFilter_fp_hlsl
delegate OSP_PostFilter_fp_cg
}
material OSP_PostFilter
{
technique
{
pass
{
cull_hardware none
cull_software none
depth_check off
vertex_program_ref Ogre/Compositor/StdQuad_vp {}
fragment_program_ref OSP_PostFilter_fp {}
texture_unit
{
content_type compositor OSP_SolidMaterialsBuffer occlusion
tex_address_mode clamp
filtering none
}
}
}
}
As you can see, right now only cg shaders are used.
In *.cpp you can see commented part where i did choice of rendering sysytem by choosing *.material file with appropriate suffix, that would bring different shaders for different rendering systems.
However it seems that there is just more pleasant way
(fragment progrem (...) unified)
Where OGRE makes choice of supported shader.
Anyway, I'm doing cg shaders for now.
Code: Select all
void OSP_SolidMaterialsBuffer_vp(
float4 inputPosition : POSITION,
out float4 outputPosition : POSITION,
out float2 outputDepth : TEXCOORD0,
uniform float4x4 worldViewProj,
uniform float4 texelOffsets,
uniform float4 depthRange
)
{
outputPosition = mul(worldViewProj, inputPosition);
outputPosition.xy += texelOffsets.zw * outputPosition.w; //solution presented by cyanbeck
outputDepth.x = smoothstep(depthRange.x,depthRange.y,outputPosition.z);
outputDepth.y = outputPosition.w;
}
void OSP_SolidMaterialsBuffer_fp(
float2 inputDepth : TEXCOORD0,
//float2 diffuse : TEXCOORD1,
out float4 outputColorAndDepth : COLOR,
uniform sampler2D texture
)
{
outputColorAndDepth = tex2D(texture, diffuse);
float finalDepth = inputDepth.x;
outputColorAndDepth.w = finalDepth;
}
void OSP_ShowDepth_fp
(
in float2 iTexCoord: TEXCOORD0,
out float4 oColor0 : COLOR0,
uniform sampler depthInAlpha: register(s0),
uniform sampler tex : register(s1)
)
{
float4 colorAndDepth = tex2D(depthInAlpha, iTexCoord);
float depth = colorAndDepth.a;
float3 color = colorAndDepth*depth;
//oColor0 = float4(tex2D(tex, float2((255-depth*200), 0)).rgb, 1);
//oColor0 = float4(color.rgb, 1);
oColor0 = float4(depth, depth, depth, 1);
}
void OSP_PostFilter_fp (
in float2 uv : TEXCOORD0,
out float4 oColor0 : COLOR0,
uniform sampler sOcclusion : register(s0)
)
{
oColor0 = float4(tex2D(sOcclusion, uv).xyz, 1);
}
Syntax of compositor+material+shaders has a lot of attributes that you need to know until you achieve goal you a re trying to achieve. (I am reading third chapter of
http://www.ogre3d.org/docs/manual/ everyday again and again).
I have a question for today:
Have you seen a very simplest example where variable is set through compositorListener, so it could be visible on
both levels: compositor and shader code?
I will use scale parameter that I want to pass from code by compositorLitener. Similat tosolution used in
http://ogre3d.org/forums/viewtopic.php?f=2&t=43238 to modify render target texture (in my case it will be depth texture).
"target_width_scaled <value example: 0.25> " will be changed there.
This parameter variable should be visible on the level of gc shader as well (so it could iterate (1/width_scale) * (1/height_scale pixels) in search of appropriate one).
Right now there is downsampling in HDR sample effect that has separate versions of material for each scale of downsampling and hard-coded sizes of textures. HDR uses textures (2^a) x (2^a) to change them into (2^(a-1)) x (2^(a-1)) textures, iteratively till achieving 1x1 texture.
It is nice solution, but not flexible enough. My task for today is to change it to few versions of downsampling (at least one that chooses maximum value in rectangle of pixels).
For next few days:
In separate pass, the texture of particle effects will be rendered while solid objects are set to unvisilbe. In this process, access to depthtexture is needed. Also scale parameters should be passed by copositorlistener for two reasons:
-so xy addresses could be referenced appropriately (modulo operations in referencing element of depth texture) while binary tepth testing.
-in this compositor, output texture will be downsampled too.
-downsampling has to make things work quicker, so for each particle, while rendering less samples of particle teture should be taken.
I am not 100% sure yet, but for the current moment I think it should be done in vertex shader by modifying output position to correst scale, isn't it?
Pseudocode of the general idea
Code: Select all
-float2 offset = //(x,y) position of texture (0,0) point from camera view
-oututPosition = multiplication of woldViewProj and inputPosition.
-outputPosition.x = (outputPosition.x-offset.x)*scaleInWidth + offset.x
-outputPosition.y = (outputPosition.y-offset.y)*scaleInHeight + offset.y
Next task:
After binary depth test:
-scale parameters,
-downsampled particle texture,
-color texture of solid objects, from g-buffer
These three input sources will be further passed to compositor that joins textures.
Scale is needed while joining (for each backround pixel, we need to reference pixel from appropriate position on particles texture).
Or particle texture could be scaled to original view size and then concatenated, but.. this is not necessary.