Commit 976b62fc authored by engineer_apple's avatar engineer_apple

Burningvideo - add Stencil Shadow Rendering (one color only and 32 bit only),...

Burningvideo - add Stencil Shadow Rendering (one color only and 32 bit only), pushed Burningvideo to 0.47

git-svn-id: svn://svn.code.sf.net/p/irrlicht/code/trunk@3337 dfc29bdd-3216-0410-991c-e03cc46cb475
parent 2a8461a4
......@@ -2,6 +2,7 @@
Changes in 1.7.1 (05.07.2010) TA
- BurningVideo
- add Normalmap Rendering ( one light only), pushed Burningvideo to 0.46
- add Stencil Shadow Rendering (one color only and 32 bit only), pushed Burningvideo to 0.47
- internal vertexformat changed
- changed fixpoint from 9 to 10 bit fract resolution
- renamed createBurningVideoDriver to createBurningVideoDriver and uses SIrrlichtCreationParameters like opengl
......
......@@ -25,7 +25,6 @@ using namespace irr;
int main()
{
// ask if user would like shadows
/*
char i;
printf("Please press 'y' if you want to use realtime shadows.\n");
......@@ -37,9 +36,7 @@ int main()
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
*/
video::E_DRIVER_TYPE driverType = video::EDT_BURNINGSVIDEO;// video::EDT_DIRECT3D9; // video::EDT_BURNINGSVIDEO; // video::EDT_OPENGL; //video::EDT_BURNINGSVIDEO;
bool shadows = true;
/*
Create device and exit if creation failed. We make the stencil flag
......
......@@ -63,7 +63,7 @@ bool CMainMenu::run(bool& outFullscreen, bool& outMusic, bool& outShadows,
box->addItem(L"OpenGL 1.5");
box->addItem(L"Direct3D 8.1");
box->addItem(L"Direct3D 9.0c");
box->addItem(L"Burning's Video 0.46");
box->addItem(L"Burning's Video 0.47");
box->addItem(L"Irrlicht Software Renderer 1.0");
box->setSelected(selected);
......
......@@ -3443,7 +3443,9 @@ void COpenGLDriver::drawStencilShadowVolume(const core::vector3df* triangles, s3
glPopAttrib();
}
//! Fills the stencil shadow with color. After the shadow volume has been drawn
//! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
//! to draw the color of the shadow.
void COpenGLDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge,
video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge)
{
......
......@@ -651,7 +651,7 @@ void CBurningVideoDriver::setTransform(E_TRANSFORMATION_STATE state, const core:
}
else
{
Transformation[ETS_WORLD].getInversePrimitive ( Transformation[ETS_WORLD_INVERSE] );
//Transformation[ETS_WORLD].getInversePrimitive ( Transformation[ETS_WORLD_INVERSE] );
Transformation[ETS_CURRENT].setbyproduct_nocheck (
Transformation[ETS_VIEW_PROJECTION],
Transformation[ETS_WORLD]
......@@ -1155,7 +1155,8 @@ const SVSize CBurningVideoDriver::vSize[] =
{ VERTEX4D_FORMAT_TEXTURE_1 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 1 },
{ VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex2TCoords),2 },
{ VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1 | VERTEX4D_FORMAT_BUMP_DOT3, sizeof(S3DVertexTangents),2 },
{ VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 2 },
{ VERTEX4D_FORMAT_TEXTURE_2 | VERTEX4D_FORMAT_COLOR_1, sizeof(S3DVertex), 2 }, // reflection map
{ 0, sizeof(f32) * 3, 0 }, // core::vector3df*
};
......@@ -1185,6 +1186,9 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest
const S3DVertex *base = ((S3DVertex*) source );
Transformation [ ETS_CURRENT].transformVect ( &dest->Pos.x, base->Pos );
//mhm ;-) maybe no goto
if ( VertexCache.vType == 4 ) goto clipandproject;
#if defined (SOFTWARE_DRIVER_2_LIGHTING) || defined ( SOFTWARE_DRIVER_2_TEXTURE_TRANSFORM )
......@@ -1443,6 +1447,7 @@ void CBurningVideoDriver::VertexCache_fill(const u32 sourceIndex, const u32 dest
#endif
clipandproject:
dest[0].flag = dest[1].flag = vSize[VertexCache.vType].Format;
// test vertex
......@@ -1501,10 +1506,18 @@ REALINLINE void CBurningVideoDriver::VertexCache_get ( s4DVertex ** face )
fillIndex < VERTEXCACHE_ELEMENT
)
{
sourceIndex = VertexCache.iType == 1 ?
((u16*)VertexCache.indices) [ VertexCache.indicesIndex ] :
((u32*)VertexCache.indices) [ VertexCache.indicesIndex ];
switch ( VertexCache.iType )
{
case 1:
sourceIndex = ((u16*)VertexCache.indices) [ VertexCache.indicesIndex ];
break;
case 2:
sourceIndex = ((u32*)VertexCache.indices) [ VertexCache.indicesIndex ];
break;
case 4:
sourceIndex = VertexCache.indicesIndex;
break;
}
VertexCache.indicesIndex += 1;
......@@ -1566,19 +1579,28 @@ REALINLINE void CBurningVideoDriver::VertexCache_get ( s4DVertex ** face )
const u32 i0 = core::if_c_a_else_0 ( VertexCache.pType != scene::EPT_TRIANGLE_FAN, VertexCache.indicesRun );
if ( VertexCache.iType == 1 )
switch ( VertexCache.iType )
{
const u16 *p = (const u16 *) VertexCache.indices;
face[0] = VertexCache_getVertex ( p[ i0 ] );
face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] );
face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] );
}
else
{
const u32 *p = (const u32 *) VertexCache.indices;
face[0] = VertexCache_getVertex ( p[ i0 ] );
face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] );
face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] );
case 1:
{
const u16 *p = (const u16 *) VertexCache.indices;
face[0] = VertexCache_getVertex ( p[ i0 ] );
face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] );
face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] );
} break;
case 2:
{
const u32 *p = (const u32 *) VertexCache.indices;
face[0] = VertexCache_getVertex ( p[ i0 ] );
face[1] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 1] );
face[2] = VertexCache_getVertex ( p[ VertexCache.indicesRun + 2] );
} break;
case 4:
face[0] = VertexCache_getVertex ( VertexCache.indicesRun + 0 );
face[1] = VertexCache_getVertex ( VertexCache.indicesRun + 1 );
face[2] = VertexCache_getVertex ( VertexCache.indicesRun + 2 );
break;
}
VertexCache.indicesRun += VertexCache.primitivePitch;
......@@ -1633,7 +1655,14 @@ void CBurningVideoDriver::VertexCache_reset ( const void* vertices, u32 vertexCo
else
VertexCache.vType = vType;
VertexCache.pType = pType;
VertexCache.iType = iType == EIT_16BIT ? 1 : 2;
switch ( iType )
{
case EIT_16BIT: VertexCache.iType = 1; break;
case EIT_32BIT: VertexCache.iType = 2; break;
default:
VertexCache.iType = iType; break;
}
switch ( VertexCache.pType )
{
......@@ -2451,13 +2480,13 @@ void CBurningVideoDriver::draw3DLine(const core::vector3df& start,
const wchar_t* CBurningVideoDriver::getName() const
{
#ifdef BURNINGVIDEO_RENDERER_BEAUTIFUL
return L"Burning's Video 0.46 beautiful";
return L"Burning's Video 0.47 beautiful";
#elif defined ( BURNINGVIDEO_RENDERER_ULTRA_FAST )
return L"Burning's Video 0.46 ultra fast";
return L"Burning's Video 0.47 ultra fast";
#elif defined ( BURNINGVIDEO_RENDERER_FAST )
return L"Burning's Video 0.46 fast";
return L"Burning's Video 0.47 fast";
#else
return L"Burning's Video 0.46";
return L"Burning's Video 0.47";
#endif
}
......@@ -2555,20 +2584,36 @@ void CBurningVideoDriver::drawStencilShadowVolume(const core::vector3df* triangl
return;
IBurningShader *shader = BurningShader [ ETR_STENCIL_SHADOW ];
CurrentShader = shader;
shader->setRenderTarget(RenderTargetSurface, ViewPort);
Material.org.MaterialType = video::EMT_SOLID;
Material.org.Lighting = false;
Material.org.ZWriteEnable = false;
Material.org.ZBuffer = ECFN_LESSEQUAL;
LightSpace.Flags &= ~VERTEXTRANSFORM;
//glStencilMask(~0);
//glStencilFunc(GL_ALWAYS, 0, ~0);
if (zfail)
{
Material.org.BackfaceCulling = false;
Material.org.FrontfaceCulling = true;
Material.org.BackfaceCulling = true;
Material.org.FrontfaceCulling = false;
shader->setParam ( 0, 0 );
shader->setParam ( 1, 1 );
shader->setParam ( 2, 0 );
drawVertexPrimitiveList ( triangles, count, 0, count/3, (video::E_VERTEX_TYPE) 4, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) 4 );
//glStencilOp(GL_KEEP, incr, GL_KEEP);
//glDrawArrays(GL_TRIANGLES,0,count);
Material.org.BackfaceCulling = true;
Material.org.FrontfaceCulling = false;
Material.org.BackfaceCulling = false;
Material.org.FrontfaceCulling = true;
shader->setParam ( 0, 0 );
shader->setParam ( 1, 2 );
shader->setParam ( 2, 0 );
drawVertexPrimitiveList ( triangles, count, 0, count/3, (video::E_VERTEX_TYPE) 4, scene::EPT_TRIANGLES, (video::E_INDEX_TYPE) 4 );
//glStencilOp(GL_KEEP, decr, GL_KEEP);
//glDrawArrays(GL_TRIANGLES,0,count);
}
......@@ -2576,87 +2621,54 @@ void CBurningVideoDriver::drawStencilShadowVolume(const core::vector3df* triangl
{
Material.org.BackfaceCulling = true;
Material.org.FrontfaceCulling = false;
shader->setParam ( 0, 0 );
shader->setParam ( 1, 0 );
shader->setParam ( 2, 1 );
//glStencilOp(GL_KEEP, GL_KEEP, incr);
//glDrawArrays(GL_TRIANGLES,0,count);
Material.org.BackfaceCulling = false;
Material.org.FrontfaceCulling = true;
shader->setParam ( 0, 0 );
shader->setParam ( 1, 0 );
shader->setParam ( 2, 2 );
//glStencilOp(GL_KEEP, GL_KEEP, decr);
//glDrawArrays(GL_TRIANGLES,0,count);
}
#if 0
if (!StencilBuffer || !count)
return;
// unset last 3d material
if (CurrentRenderMode == ERM_3D &&
static_cast<u32>(Material.MaterialType) < MaterialRenderers.size())
{
MaterialRenderers[Material.MaterialType].Renderer->OnUnsetMaterial();
ResetRenderStates = true;
}
// store current OpenGL state
glPushAttrib(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_ENABLE_BIT |
GL_POLYGON_BIT | GL_STENCIL_BUFFER_BIT);
glDisable(GL_LIGHTING);
glDisable(GL_FOG);
glDepthFunc(GL_LEQUAL);
glDepthMask(GL_FALSE); // no depth buffer writing
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); // no color buffer drawing
glEnable(GL_STENCIL_TEST);
glEnable(GL_POLYGON_OFFSET_FILL);
glPolygonOffset(0.0f, 1.0f);
}
glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3,GL_FLOAT,sizeof(core::vector3df),&triangles[0]);
glStencilMask(~0);
glStencilFunc(GL_ALWAYS, 0, ~0);
//! Fills the stencil shadow with color. After the shadow volume has been drawn
//! into the stencil buffer using IVideoDriver::drawStencilShadowVolume(), use this
//! to draw the color of the shadow.
void CBurningVideoDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge,
video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge)
{
if (!StencilBuffer)
return;
GLenum incr = GL_INCR;
GLenum decr = GL_DECR;
if (FeatureAvailable[IRR_EXT_stencil_wrap])
{
incr = GL_INCR_WRAP_EXT;
decr = GL_DECR_WRAP_EXT;
}
// draw a shadow rectangle covering the entire screen using stencil buffer
const u32 h = RenderTargetSurface->getDimension().Height;
const u32 w = RenderTargetSurface->getDimension().Width;
tVideoSample *dst;
u32 *stencil;
for ( u32 y = 0; y < h; ++y )
{
glEnable(GL_CULL_FACE);
if (zfail)
{
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, incr, GL_KEEP);
glDrawArrays(GL_TRIANGLES,0,count);
dst = (tVideoSample*)RenderTargetSurface->lock() + ( y * w );
stencil = (u32*) StencilBuffer->lock() + ( y * w );
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, decr, GL_KEEP);
glDrawArrays(GL_TRIANGLES,0,count);
}
else // zpass
for ( u32 x = 0; x < w; ++x )
{
glCullFace(GL_BACK);
glStencilOp(GL_KEEP, GL_KEEP, incr);
glDrawArrays(GL_TRIANGLES,0,count);
glCullFace(GL_FRONT);
glStencilOp(GL_KEEP, GL_KEEP, decr);
glDrawArrays(GL_TRIANGLES,0,count);
if ( stencil[x] > 1 )
{
dst[x] = PixelBlend32 ( dst[x], leftUpEdge.color );
}
}
}
glDisableClientState(GL_VERTEX_ARRAY); //not stored on stack
glPopAttrib();
#endif
}
void CBurningVideoDriver::drawStencilShadow(bool clearStencilBuffer, video::SColor leftUpEdge,
video::SColor rightUpEdge, video::SColor leftDownEdge, video::SColor rightDownEdge)
{
StencilBuffer->clear();
#if 0
if (!StencilBuffer)
return;
......
......@@ -159,6 +159,7 @@ namespace video
virtual core::dimension2du getMaxTextureSize() const;
virtual IDepthBuffer * getDepthBuffer () { return DepthBuffer; }
virtual IStencilBuffer * getStencilBuffer () { return StencilBuffer; }
protected:
......
......@@ -29,7 +29,7 @@
// define render case
#define SUBTEXEL
#define INVERSE_W
//#define INVERSE_W
#define USE_ZBUFFER
#define USE_SBUFFER
......@@ -85,10 +85,15 @@ public:
//! draws an indexed triangle list
virtual void drawTriangle ( const s4DVertex *a,const s4DVertex *b,const s4DVertex *c );
virtual void setParam ( u32 index, f32 value);
private:
void scanline ();
// fragment shader
typedef void (CTRStencilShadow::*tFragmentShader) ();
void fragment_zfail_decr ();
void fragment_zfail_incr ();
tFragmentShader fragmentShader;
sScanConvertData scan;
sScanLineData line;
......@@ -108,9 +113,30 @@ CTRStencilShadow::CTRStencilShadow(CBurningVideoDriver* driver)
/*!
*/
void CTRStencilShadow::scanline ()
void CTRStencilShadow::setParam ( u32 index, f32 value)
{
u32 val = (u32) value;
// glStencilOp (fail,zfail,zpass
if ( index == 1 && val == 1 )
{
fragmentShader = &CTRStencilShadow::fragment_zfail_incr;
}
else
if ( index == 1 && val == 2 )
{
fragmentShader = &CTRStencilShadow::fragment_zfail_decr;
}
}
/*!
*/
void CTRStencilShadow::fragment_zfail_decr ()
{
tVideoSample *dst;
//tVideoSample *dst;
#ifdef USE_ZBUFFER
fp24 *z;
......@@ -204,7 +230,7 @@ void CTRStencilShadow::scanline ()
#endif
#endif
dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
//dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
#ifdef USE_ZBUFFER
z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
......@@ -230,24 +256,167 @@ void CTRStencilShadow::scanline ()
if ( line.z[0] < z[i] )
#endif
#ifdef CMP_W
if ( line.w[0] >= z[i] )
if ( line.w[0] < z[i] )
#endif
{
#ifdef INVERSE_W
inversew = fix_inverse32 ( line.w[0] );
// zfail
stencil[i] -= 1;
}
#ifdef IPOL_Z
line.z[0] += slopeZ;
#endif
#ifdef IPOL_W
line.w[0] += slopeW;
#endif
#ifdef IPOL_C0
line.c[0][0] += slopeC[0];
#endif
#ifdef IPOL_T0
line.t[0][0] += slopeT[0];
#endif
#ifdef IPOL_T1
line.t[1][0] += slopeT[1];
#endif
#ifdef IPOL_T2
line.t[2][0] += slopeT[2];
#endif
#ifdef IPOL_L0
line.l[0][0] += slopeL[0];
#endif
}
}
/*!
*/
void CTRStencilShadow::fragment_zfail_incr ()
{
//tVideoSample *dst;
#ifdef USE_ZBUFFER
fp24 *z;
#endif
#ifdef USE_SBUFFER
u32 *stencil;
#endif
s32 xStart;
s32 xEnd;
s32 dx;
#ifdef SUBTEXEL
f32 subPixel;
#endif
#ifdef IPOL_Z
f32 slopeZ;
#endif
#ifdef IPOL_W
fp24 slopeW;
#endif
#ifdef IPOL_C0
sVec4 slopeC[MATERIAL_MAX_COLORS];
#endif
#ifdef IPOL_T0
sVec2 slopeT[BURNING_MATERIAL_MAX_TEXTURES];
#endif
#ifdef IPOL_L0
sVec3 slopeL[BURNING_MATERIAL_MAX_TANGENT];
#endif
// apply top-left fill-convention, left
xStart = core::ceil32( line.x[0] );
xEnd = core::ceil32( line.x[1] ) - 1;
dx = xEnd - xStart;
#else
if ( dx < 0 )
return;
// slopes
const f32 invDeltaX = core::reciprocal_approxim ( line.x[1] - line.x[0] );
#ifdef IPOL_Z
slopeZ = (line.z[1] - line.z[0]) * invDeltaX;
#endif
#ifdef IPOL_W
slopeW = (line.w[1] - line.w[0]) * invDeltaX;
#endif
#ifdef IPOL_C0
slopeC[0] = (line.c[0][1] - line.c[0][0]) * invDeltaX;
#endif
#ifdef IPOL_T0
slopeT[0] = (line.t[0][1] - line.t[0][0]) * invDeltaX;
#endif
#ifdef IPOL_T1
slopeT[1] = (line.t[1][1] - line.t[1][0]) * invDeltaX;
#endif
#ifdef IPOL_T2
slopeT[2] = (line.t[2][1] - line.t[2][0]) * invDeltaX;
#endif
#ifdef IPOL_L0
slopeL[0] = (line.l[0][1] - line.l[0][0]) * invDeltaX;
#endif
dst[i] = 0xFFFFFFFF;
#ifdef SUBTEXEL
subPixel = ( (f32) xStart ) - line.x[0];
#ifdef IPOL_Z
line.z[0] += slopeZ * subPixel;
#endif
#ifdef IPOL_W
line.w[0] += slopeW * subPixel;
#endif
#ifdef IPOL_C0
line.c[0][0] += slopeC[0] * subPixel;
#endif
#ifdef IPOL_T0
line.t[0][0] += slopeT[0] * subPixel;
#endif
#ifdef IPOL_T1
line.t[1][0] += slopeT[1] * subPixel;
#endif
#ifdef IPOL_T2
line.t[2][0] += slopeT[2] * subPixel;
#endif
#ifdef IPOL_L0
line.l[0][0] += slopeL[0] * subPixel;
#endif
#endif
//dst = (tVideoSample*)RenderTarget->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
#ifdef WRITE_Z
z[i] = line.z[0];
#ifdef USE_ZBUFFER
z = (fp24*) DepthBuffer->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
#endif
#ifdef WRITE_W
z[i] = line.w[0];
#ifdef USE_SBUFFER
stencil = (u32*) Stencil->lock() + ( line.y * RenderTarget->getDimension().Width ) + xStart;
#endif
#ifdef INVERSE_W
f32 inversew;
#endif
#ifdef IPOL_C0
tFixPoint r3, g3, b3;
#endif
for ( s32 i = 0; i <= dx; i++ )
{
#ifdef CMP_Z
if ( line.z[0] < z[i] )
#endif
#ifdef CMP_W
if ( line.w[0] < z[i] )
#endif
{
// zfail
stencil[i] += 1;
}
#ifdef IPOL_Z
......@@ -485,7 +654,7 @@ void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons
#endif
// render a scanline
scanline ();
(this->*fragmentShader) ();
scan.x[0] += scan.slopeX[0];
scan.x[1] += scan.slopeX[1];
......@@ -693,7 +862,7 @@ void CTRStencilShadow::drawTriangle ( const s4DVertex *a,const s4DVertex *b,cons
#endif
// render a scanline
scanline ();
(this->*fragmentShader) ();
scan.x[0] += scan.slopeX[0];
scan.x[1] += scan.slopeX[1];
......
......@@ -39,6 +39,11 @@ namespace video
DepthBuffer = (CDepthBuffer*) driver->getDepthBuffer ();
if ( DepthBuffer )
DepthBuffer->grab();
Stencil = (CStencilBuffer*) driver->getStencilBuffer ();
if ( Stencil )
Stencil->grab();
}
......@@ -51,6 +56,9 @@ namespace video
if (DepthBuffer)
DepthBuffer->drop();
if (Stencil)
Stencil->drop();
for ( u32 i = 0; i != BURNING_MATERIAL_MAX_TEXTURES; ++i )
{
if ( IT[i].Texture )
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment