khanat-opennel-code/code/nel/src/3d/motion_blur.cpp

128 lines
3.7 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "std3d.h"
#include "nel/misc/common.h"
#include "nel/3d/motion_blur.h"
#include "nel/3d/driver.h"
#include "nel/3d/texture.h"
#include "nel/3d/texture_blank.h"
#include "nel/3d/material.h"
namespace NL3D {
CMotionBlur::CMotionBlur() : _Tex(NULL), _X(0), _Y(0), _W(0), _H(0)
{
}
void CMotionBlur::startMotionBlur(uint x, uint y, uint width, uint height)
{
nlassert(width > 0 && height > 0) ;
_X = x ;
_Y = y ;
_W = width ;
_H = height ;
_Tex = new CTextureBlank ;
_Tex->resize(NLMISC::raiseToNextPowerOf2(width), NLMISC::raiseToNextPowerOf2(height)) ;
}
void CMotionBlur::releaseMotionBlur()
{
_Tex = NULL ;
_X = _Y = _W = _H = 0 ;
}
void CMotionBlur::performMotionBlur(IDriver *driver, float motionBlurAmount)
{
nlassert(_Tex) ; //start motion blur has not been called !!
nlassert(driver) ;
nlassert(motionBlurAmount >= 0.f && motionBlurAmount <= 1.f) ;
static CVertexBuffer vb ;
vb.setVertexFormat(CVertexBuffer::PositionFlag | CVertexBuffer::TexCoord0Flag ) ;
vb.setNumVertices(4) ;
uint32 width, height ;
driver->getWindowSize(width, height) ;
float widthRatio = _W / (float) NLMISC::raiseToNextPowerOf2 (_W) ;
float heightRatio = _H / (float) NLMISC::raiseToNextPowerOf2 (_H) ;
driver->setFrustum(0, (float) width, 0, (float) height, -1, 1, false) ;
static CMaterial mbMat ;
{
CVertexBufferReadWrite vba;
vb.lock (vba);
for (uint sn = 0 ; sn < 2 ; ++sn)
{
vba.setTexCoord(0, sn, CUV(0, 0)) ;
vba.setTexCoord(1, sn, CUV(widthRatio, 0)) ;
vba.setTexCoord(2, sn, CUV(widthRatio, heightRatio)) ;
vba.setTexCoord(3, sn, CUV(0, heightRatio)) ;
}
static bool matSetup = false ; // set to true when mbMat has Been setup
if (!matSetup)
{
mbMat.setBlend(true) ;
mbMat.setBlendFunc(CMaterial::srcalpha, CMaterial::invsrcalpha) ;
mbMat.setZWrite(false) ;
mbMat.setZFunc(CMaterial::always) ;
// stage 0
mbMat.setTexture(0, _Tex) ;
mbMat.texEnvOpRGB(0, CMaterial::Replace );
mbMat.texEnvArg0Alpha(0, CMaterial::Diffuse, CMaterial::SrcAlpha);
mbMat.texEnvOpAlpha(0, CMaterial::Replace);
mbMat.setDoubleSided(true) ;
matSetup = true ;
}
mbMat.setColor(CRGBA(255, 255, 255, (uint8) (255.f * motionBlurAmount) ) ) ;
vba.setVertexCoord(0, CVector((float) _X, 0, 0) ) ;
vba.setVertexCoord(1, CVector((float) (_X + _W), 0 ,0) ) ;
vba.setVertexCoord(2, CVector((float) (_X + _W), 0, (float) (_Y + _H) ) );
vba.setVertexCoord(3, CVector(0 , 0, (float) (_Y + _H) ) ) ;
}
driver->setupViewMatrix(CMatrix::Identity) ;
driver->setupModelMatrix(CMatrix::Identity) ;
driver->activeVertexBuffer(vb) ;
driver->renderRawQuads(mbMat, 0, 1) ;
// blit back frame buffer to save this frame
// todo hulud : use the new render to texture interface
// driver->copyFrameBufferToTexture(_Tex, 0, 0, 0, _X, _Y, _W, _H) ;
}
} // NL3D