How do use native OpenGL and Direct3D calls inside Ogre by Assaf Raman- http://www.ogre3d.org/forums/viewtopic.php?f=1&t=43156
/*
-----------------------------------------------------------------------------
This source file is part of OGRE
(Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/
Copyright (c) 2000-2006 Torus Knot Software Ltd
Also see acknowledgements in Readme.html
You may use this sample code for anything you like, it is not covered by the
LGPL like the rest of the engine.
-----------------------------------------------------------------------------
*/
/**
\file
NativeRenderSystemCommands.h
\brief
A sample demonstrating how to add render system specific native code to an existing scene.
I based this sample on the SkyDome sample, just added a FrameListener
*/
#include "..\..\SkyDome\include\SkyDome.h"
#include <gl\gl.h>
#include <d3d9.h>
class RenderSystemCommandsRenderQueueListener : public RenderQueueListener
{
protected:
MovableObject* mObject;
const Camera* mCamera;
SceneManager* mSceneMgr;
RenderWindow* mWindow;
virtual void Render() = 0;
virtual void PreRender() = 0;
virtual void PostRender() = 0;
public:
RenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
mObject(object),
mCamera(camera),
mWindow(window),
mSceneMgr(sceneMgr)
{
}
virtual void renderQueueStarted(uint8 queueGroupId, const String& invocation,
bool& skipThisInvocation) { }
virtual void renderQueueEnded(uint8 queueGroupId, const String& invocation,
bool& repeatThisInvocation)
{
// Set wanted render queue here - make sure there are - make sure that something is on
// this queue - else you will never pass this if.
if (queueGroupId != RENDER_QUEUE_MAIN)
return;
PreRender();
Render();
PostRender();
}
};
class OpenGLRenderSystemCommandsRenderQueueListener : public RenderSystemCommandsRenderQueueListener
{
protected:
virtual void PreRender()
{
// save matrices
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glMatrixMode(GL_TEXTURE);
glPushMatrix();
glLoadIdentity(); //Texture addressing should start out as direct.
RenderSystem* renderSystem = mObject->_getManager()->getDestinationRenderSystem();
Node* parentNode = mObject->getParentNode();
renderSystem->_setWorldMatrix(parentNode->_getFullTransform());
renderSystem->_setViewMatrix(mCamera->getViewMatrix());
renderSystem->_setProjectionMatrix(mCamera->getProjectionMatrixRS());
static Pass* clearPass = NULL;
if (!clearPass)
{
MaterialPtr clearMat = MaterialManager::getSingleton().getByName("BaseWhite");
clearPass = clearMat->getTechnique(0)->getPass(0);
}
//Set a clear pass to give the renderer a clear renderstate
mSceneMgr->_setPass(clearPass, true, false);
// save attribs
glPushAttrib(GL_ALL_ATTRIB_BITS);
}
virtual void PostRender()
{
// restore original state
glPopAttrib();
// restore matrices
glMatrixMode(GL_TEXTURE);
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
glPopMatrix();
}
public:
OpenGLRenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
RenderSystemCommandsRenderQueueListener(object, camera, window, sceneMgr)
{
}
};
class CubeOpenGLRenderSystemCommandsRenderQueueListener : public OpenGLRenderSystemCommandsRenderQueueListener
{
protected:
void Render()
{
GLboolean depthTestEnabled=glIsEnabled(GL_DEPTH_TEST);
glDisable(GL_DEPTH_TEST);
GLboolean stencilTestEnabled = glIsEnabled(GL_STENCIL_TEST);
glDisable(GL_STENCIL_TEST);
glDisable(GL_TEXTURE_2D);
glDisable(GL_LIGHTING);
glScalef(30.0, 30.0, 30.0);
// I took the following sample code from here: http://www.oreillynet.com/network/2000/06/23/magazine/cube.c
// OK, let's start drawing our planer quads.
glBegin(GL_QUADS);
// Bottom Face. Red, 75% opaque, magnified texture
glNormal3f( 0.0f, -1.0f, 0.0f); // Needed for lighting
glColor4f(0.9,0.2,0.2,.75); // Basic polygon color
glTexCoord2f(0.800f, 0.800f); glVertex3f(-1.0f, -1.0f, -1.0f);
glTexCoord2f(0.200f, 0.800f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.200f, 0.200f); glVertex3f( 1.0f, -1.0f, 1.0f);
glTexCoord2f(0.800f, 0.200f); glVertex3f(-1.0f, -1.0f, 1.0f);
// Top face; offset. White, 50% opaque.
glNormal3f( 0.0f, 1.0f, 0.0f); glColor4f(0.5,0.5,0.5,.5);
glTexCoord2f(0.005f, 1.995f); glVertex3f(-1.0f, 1.3f, -1.0f);
glTexCoord2f(0.005f, 0.005f); glVertex3f(-1.0f, 1.3f, 1.0f);
glTexCoord2f(1.995f, 0.005f); glVertex3f( 1.0f, 1.3f, 1.0f);
glTexCoord2f(1.995f, 1.995f); glVertex3f( 1.0f, 1.3f, -1.0f);
// Far face. Green, 50% opaque, non-uniform texture cooridinates.
glNormal3f( 0.0f, 0.0f,-1.0f); glColor4f(0.2,0.9,0.2,.5);
glTexCoord2f(0.995f, 0.005f); glVertex3f(-1.0f, -1.0f, -1.3f);
glTexCoord2f(2.995f, 2.995f); glVertex3f(-1.0f, 1.0f, -1.3f);
glTexCoord2f(0.005f, 0.995f); glVertex3f( 1.0f, 1.0f, -1.3f);
glTexCoord2f(0.005f, 0.005f); glVertex3f( 1.0f, -1.0f, -1.3f);
// Right face. Blue; 25% opaque
glNormal3f( 1.0f, 0.0f, 0.0f); glColor4f(0.2,0.2,0.9,.25);
glTexCoord2f(0.995f, 0.005f); glVertex3f( 1.0f, -1.0f, -1.0f);
glTexCoord2f(0.995f, 0.995f); glVertex3f( 1.0f, 1.0f, -1.0f);
glTexCoord2f(0.005f, 0.995f); glVertex3f( 1.0f, 1.0f, 1.0f);
glTexCoord2f(0.005f, 0.005f); glVertex3f( 1.0f, -1.0f, 1.0f);
// Front face; offset. Multi-colored, 50% opaque.
glNormal3f( 0.0f, 0.0f, 1.0f);
glColor4f( 0.9f, 0.2f, 0.2f, 0.5f);
glTexCoord2f( 0.005f, 0.005f); glVertex3f(-1.0f, -1.0f, 1.3f);
glColor4f( 0.2f, 0.9f, 0.2f, 0.5f);
glTexCoord2f( 0.995f, 0.005f); glVertex3f( 1.0f, -1.0f, 1.3f);
glColor4f( 0.2f, 0.2f, 0.9f, 0.5f);
glTexCoord2f( 0.995f, 0.995f); glVertex3f( 1.0f, 1.0f, 1.3f);
glColor4f( 0.1f, 0.1f, 0.1f, 0.5f);
glTexCoord2f( 0.005f, 0.995f); glVertex3f(-1.0f, 1.0f, 1.3f);
// Left Face; offset. Yellow, varying levels of opaque.
glNormal3f(-1.0f, 0.0f, 0.0f);
glColor4f(0.9,0.9,0.2,0.0);
glTexCoord2f(0.005f, 0.005f); glVertex3f(-1.3f, -1.0f, -1.0f);
glColor4f(0.9,0.9,0.2,0.66);
glTexCoord2f(0.995f, 0.005f); glVertex3f(-1.3f, -1.0f, 1.0f);
glColor4f(0.9,0.9,0.2,1.0);
glTexCoord2f(0.995f, 0.995f); glVertex3f(-1.3f, 1.0f, 1.0f);
glColor4f(0.9,0.9,0.2,0.33);
glTexCoord2f(0.005f, 0.995f); glVertex3f(-1.3f, 1.0f, -1.0f);
// All polygons have been drawn.
glEnd();
if (depthTestEnabled)
{
glEnable(GL_DEPTH_TEST);
}
if (stencilTestEnabled)
{
glEnable(GL_STENCIL_TEST);
}
}
public:
CubeOpenGLRenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
OpenGLRenderSystemCommandsRenderQueueListener(object, camera, window, sceneMgr)
{
}
};
/////////////////////////////////////////
class D3D9RenderSystemCommandsRenderQueueListener : public RenderSystemCommandsRenderQueueListener
{
protected:
virtual void PreRender()
{
RenderSystem* renderSystem = mObject->_getManager()->getDestinationRenderSystem();
Node* parentNode = mObject->getParentNode();
renderSystem->_setWorldMatrix(parentNode->_getFullTransform());
renderSystem->_setViewMatrix(mCamera->getViewMatrix());
renderSystem->_setProjectionMatrix(mCamera->getProjectionMatrixRS());
static Pass* clearPass = NULL;
if (!clearPass)
{
MaterialPtr clearMat = MaterialManager::getSingleton().getByName("BaseWhite");
clearPass = clearMat->getTechnique(0)->getPass(0);
}
//Set a clear pass to give the renderer a clear renderstate
mSceneMgr->_setPass(clearPass, true, false);
}
virtual void PostRender()
{
}
public:
D3D9RenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
RenderSystemCommandsRenderQueueListener(object, camera, window, sceneMgr)
{
}
};
class CubeD3D9RenderSystemCommandsRenderQueueListener : public D3D9RenderSystemCommandsRenderQueueListener
{
protected:
void Render()
{
LPDIRECT3DDEVICE9 pd3dDevice = NULL; // Our rendering device
LPDIRECT3DVERTEXBUFFER9 pVB = NULL; // Buffer to hold vertices
RenderSystem* renderSystem = mObject->_getManager()->getDestinationRenderSystem();
mWindow->getCustomAttribute( "D3DDEVICE", &pd3dDevice );
pd3dDevice->SetRenderState(D3DRS_LIGHTING, false);
pd3dDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, TVC_DIFFUSE);
// A structure for our custom vertex type
struct CUSTOMVERTEX
{
Vector3 pos; // The untransformed, 3D position for the vertex
Vector3 normal; // The untransformed, 3D position for the vertex
DWORD color; // The vertex color
};
// Our custom FVF, which describes our custom vertex structure
#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_NORMAL|D3DFVF_DIFFUSE)
#define SCALE_FACTOR 30
// Initialize three vertices for rendering a triangle
static const CUSTOMVERTEX cubeVertices[] =
{
// Bottom Face.
{ Vector3(-1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
{ Vector3( 1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
{ Vector3( 1.0f, -1.0f, 1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
{ Vector3( 1.0f, -1.0f, 1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
{ Vector3(-1.0f, -1.0f, 1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
{ Vector3(-1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, -1.0f, 0.0f), 0xff000000, },
// Top Face.
{ Vector3(-1.0f, 1.3f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
{ Vector3(-1.0f, 1.3f, 1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
{ Vector3( 1.0f, 1.3f, 1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
{ Vector3( 1.0f, 1.3f, 1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
{ Vector3( 1.0f, 1.3f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
{ Vector3(-1.0f, 1.3f, -1.0f) * SCALE_FACTOR, Vector3( 0.0f, 1.0f, 0.0f), 0xffffff00, },
// Far Face.
{ Vector3(-1.0f, -1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
{ Vector3(-1.0f, 1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
{ Vector3( 1.0f, 1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
{ Vector3( 1.0f, 1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
{ Vector3( 1.0f, -1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
{ Vector3(-1.0f, -1.0f, -1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f,-1.0f), 0x00ff0000, },
// Right Face.
{ Vector3( 1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
{ Vector3( 1.0f, 1.0f, -1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
{ Vector3( 1.0f, 1.0f, 1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
{ Vector3( 1.0f, 1.0f, 1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
{ Vector3( 1.0f, -1.0f, 1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
{ Vector3( 1.0f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( 1.0f, 0.0f, 0.0f), 0x0000ff00, },
// Front Face.
{ Vector3(-1.0f, -1.0f, 1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0xff00ff00, },
{ Vector3( 1.0f, -1.0f, 1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0x00ffff00, },
{ Vector3( 1.0f, 1.0f, 1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0x0000ff00, },
{ Vector3( 1.0f, 1.0f, 1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0x0000ff00, },
{ Vector3(-1.0f, 1.0f, 1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0xffffff00, },
{ Vector3(-1.0f, -1.0f, 1.3f) * SCALE_FACTOR, Vector3( 0.0f, 0.0f, 1.0f), 0xff00ff00, },
// Left Face.
{ Vector3(-1.3f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
{ Vector3(-1.3f, -1.0f, 1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
{ Vector3(-1.3f, 1.0f, 1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
{ Vector3(-1.3f, 1.0f, 1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
{ Vector3(-1.3f, 1.0f, -1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
{ Vector3(-1.3f, -1.0f, -1.0f) * SCALE_FACTOR, Vector3( -1.0f, 0.0f, 0.0f), 0xffff0000, },
};
UINT primitiveCount = sizeof(cubeVertices) / sizeof(CUSTOMVERTEX) / 3;
// Create the vertex buffer.
if( FAILED( pd3dDevice->CreateVertexBuffer( sizeof(cubeVertices),
0, D3DFVF_CUSTOMVERTEX,
D3DPOOL_DEFAULT, &pVB, NULL ) ) )
{
return;//E_FAIL;
}
// Fill the vertex buffer.
VOID* pVertices;
if( FAILED( pVB->Lock( 0, sizeof(cubeVertices), (void**)&pVertices, 0 ) ) )
return;// E_FAIL;
memcpy( pVertices, cubeVertices, sizeof(cubeVertices) );
pVB->Unlock();
// Render the vertex buffer contents
pd3dDevice->SetStreamSource( 0, pVB, 0, sizeof(CUSTOMVERTEX) );
pd3dDevice->SetFVF( D3DFVF_CUSTOMVERTEX );
pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, primitiveCount );
pVB->Release();
}
public:
CubeD3D9RenderSystemCommandsRenderQueueListener(MovableObject* object, const Camera* camera, RenderWindow* window, SceneManager* sceneMgr) :
D3D9RenderSystemCommandsRenderQueueListener(object, camera, window, sceneMgr)
{
}
};
/////////////////////////////////////////
class NativeRenderSystemCommandsApplication : public SkyDomeApplication
{
public:
NativeRenderSystemCommandsApplication()
{
}
protected:
RenderQueueListener * mRenderSystemCommandsRenderQueueListener;
// Just override the mandatory create scene method
void createScene(void)
{
SkyDomeApplication::createScene();
ManualObject *manObj; // we will use this Manual Object as a reference point for the native rendering
manObj = mSceneMgr->createManualObject("sampleArea");
// Attach to child of root node, better for culling (otherwise bounds are the combination of the 2)
mSceneMgr->getRootSceneNode()->createChildSceneNode()->attachObject(manObj);
String RenderSystemName = mSceneMgr->getDestinationRenderSystem()->getName();
mRenderSystemCommandsRenderQueueListener = NULL;
if ("OpenGL Rendering Subsystem" == RenderSystemName)
{
mRenderSystemCommandsRenderQueueListener = new CubeOpenGLRenderSystemCommandsRenderQueueListener(
manObj, mCamera, mWindow, mSceneMgr);
mSceneMgr->addRenderQueueListener(mRenderSystemCommandsRenderQueueListener);
}
if ("Direct3D9 Rendering Subsystem" == RenderSystemName)
{
mRenderSystemCommandsRenderQueueListener = new CubeD3D9RenderSystemCommandsRenderQueueListener(
manObj, mCamera, mWindow, mSceneMgr);
mSceneMgr->addRenderQueueListener(mRenderSystemCommandsRenderQueueListener);
}
}
void destroyScene()
{
if (mRenderSystemCommandsRenderQueueListener)
{
mSceneMgr->removeRenderQueueListener(mRenderSystemCommandsRenderQueueListener);
delete mRenderSystemCommandsRenderQueueListener;
mRenderSystemCommandsRenderQueueListener = NULL;
}
SkyDomeApplication::destroyScene();
}
};
/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2006 Torus Knot Software Ltd Also see acknowledgements in Readme.html You may use this sample code for anything you like, it is not covered by the LGPL like the rest of the engine. ----------------------------------------------------------------------------- */ /** \file NativeRenderSystemCommands.cpp \brief A sample demonstrating how to add render system specific native code to an existing scene. */ #include "NativeRenderSystemCommands.h" #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 NativeRenderSystemCommandsApplication 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