DirectJ adds support for DirectX 9 in Java. The design is meant to be as close to the original C/C++ API as possible. This is to ensure ease of use for current DirectX 9 developers to switch between the original and the Java implementation. Currently, only Windows is supported, but with projects such as Wine, other Unix based platforms could use the API.
The following code creates the screenshots listed below:
public class D3DTest {
public static void main(String[] args) {
// Create D3D
IDirect3D9 d3d = D3D9.Direct3DCreate9( D3D9.D3D_SDK_VERSION );
int width = 800, height = 600;
JFrame f = new JFrame();
f.setSize( width, height );
f.setTitle( "LWJGL D3D Example" );
// Create the canvas
AWTD3DCanvas can = new AWTD3DCanvas();
f.getContentPane().add( can, BorderLayout.CENTER );
f.setVisible( true );
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
// Get the display mode from the default adapter
D3DDISPLAYMODE dm = new D3DDISPLAYMODE();
d3d.GetAdapterDisplayMode( D3D9.D3DADAPTER_DEFAULT, dm );
// Setup the presentation parameters for the device
D3DPRESENT_PARAMETERS m_d3dpp = new D3DPRESENT_PARAMETERS();
m_d3dpp.BackBufferFormat = dm.Format;
m_d3dpp.BackBufferCount = 1;
m_d3dpp.MultiSampleType = D3DMULTISAMPLE_TYPE.D3DMULTISAMPLE_NONE;
m_d3dpp.hDeviceWindow = can;
m_d3dpp.Windowed = true;
m_d3dpp.BackBufferWidth = width;
m_d3dpp.BackBufferHeight = height;
m_d3dpp.EnableAutoDepthStencil = true;
m_d3dpp.AutoDepthStencilFormat = D3DFORMAT.D3DFMT_D16;
m_d3dpp.Flags = 0;
m_d3dpp.FullScreen_RefreshRateInHz = 0;
m_d3dpp.SwapEffect = D3DSWAPEFFECT.D3DSWAPEFFECT_FLIP;
m_d3dpp.PresentationInterval = D3D9.D3DPRESENT_INTERVAL_ONE;
// Create the device interface
IDirect3DDevice9 dev = new IDirect3DDevice9();
int r = d3d.CreateDevice( D3D9.D3DADAPTER_DEFAULT,
D3DDEVTYPE.D3DDEVTYPE_HAL,
can,
D3D9.D3DCREATE_HARDWARE_VERTEXPROCESSING,
m_d3dpp,
dev );
if( D3D9.FAILED( r ) ) {
r = d3d.CreateDevice( D3D9.D3DADAPTER_DEFAULT,
D3DDEVTYPE.D3DDEVTYPE_SW,
can,
D3D9.D3DCREATE_HARDWARE_VERTEXPROCESSING,
m_d3dpp,
dev );
if( D3D9.FAILED( r ) ) {
r = d3d.CreateDevice( D3D9.D3DADAPTER_DEFAULT,
D3DDEVTYPE.D3DDEVTYPE_HAL,
can,
D3D9.D3DCREATE_SOFTWARE_VERTEXPROCESSING,
m_d3dpp,
dev );
if( D3D9.FAILED( r ) ) {
r = d3d.CreateDevice( D3D9.D3DADAPTER_DEFAULT,
D3DDEVTYPE.D3DDEVTYPE_SW,
can,
D3D9.D3DCREATE_SOFTWARE_VERTEXPROCESSING,
m_d3dpp,
dev );
if( D3D9.FAILED( r ) ) {
throw new RuntimeException( "Unable to create device" );
}
}
}
}
D3DCOLOR color = D3D9.D3DCOLOR_XRGB( 200, 100, 50 ),
cc =D3D9.D3DCOLOR_ARGB( 200, 100, 50, 255 );
// Create the view port
D3DVIEWPORT9 vp = new D3DVIEWPORT9();
vp.X = vp.Y = 0;
vp.Width = width;
vp.Height = height;
vp.MinZ = 0.0f;
vp.MaxZ = 1.0f;
dev.SetViewport( vp );
// Create a buffer to render
float w = 0f, h = .5f;
ByteBuffer bb = BufferUtils.createByteBuffer( 64 );
bb.rewind();
bb.putFloat( w ).putFloat( w ).putFloat( 0.0f ).putInt( cc.asInt() );
bb.putFloat( w ).putFloat( h ).putFloat( 0.0f ).putInt( -cc.asInt() );
bb.putFloat( h ).putFloat( w ).putFloat( 0.0f ).putInt( -cc.asInt() );
bb.putFloat( h ).putFloat( h ).putFloat( 0.0f ).putInt( cc.asInt() );
bb.rewind();
// Create a vertex buffer
IDirect3DVertexBuffer9 vb = new IDirect3DVertexBuffer9();
r = dev.CreateVertexBuffer( 64,
0,
D3D9.D3DFVF_XYZ | D3D9.D3DFVF_DIFFUSE,
D3DPOOL.D3DPOOL_MANAGED,
vb,
0L );
if( D3D9.FAILED( r ) ) {
throw new RuntimeException( "" + r );
}
// Set the vertex buffers data
ByteBuffer vbb = BufferUtils.createByteBuffer( 64 );
if( D3D9.SUCCEEDED( vb.Lock( 0, 0, vbb, 0 ) ) ) {
vbb.putFloat( -w ).putFloat( -w ).putFloat( 0.0f ).putInt( -cc.asInt() );
vbb.putFloat( -w ).putFloat( -h ).putFloat( 0.0f ).putInt( cc.asInt() );
vbb.putFloat( -h ).putFloat( -w ).putFloat( 0.0f ).putInt( cc.asInt() );
vbb.putFloat( -h ).putFloat( -h ).putFloat( 0.0f ).putInt( -cc.asInt() );
vbb.rewind();
vb.Unlock();
}
// Create a light and enable it
D3DLIGHT9 l1 = new D3DLIGHT9();
l1.Diffuse.fromColor( 1.0f, 1.0f, 0, 1 );
l1.Ambient.fromColor( l1.Diffuse );
l1.Specular.fromColor( 1, 1, 1, 1.0f );
l1.Range = 1000;
l1.Falloff = 100;
l1.Attenuation0 = 1;
l1.Direction.fromVector( -.5f, -1, 0 );
l1.Position.fromVector( 0, 5, 0 );
dev.SetLight( 0, l1 );
dev.LightEnable( 0, true );
// Create a material so the light has something it work from
D3DMATERIAL9 m1 = new D3DMATERIAL9();
m1.Diffuse.fromColor( 0.5f, 0.5f, 0.5f, 1 );
m1.Ambient.fromColor( m1.Diffuse );
m1.Emissive.fromColor( 0, .1f, 0, 1.0f );
m1.Specular.fromColor( 0.1f, 0, 0, 1 );
m1.Power = 1.0f;
dev.SetMaterial( m1 );
// Create the box with normals
ByteBuffer vblight = BufferUtils.createByteBuffer( 96 );
vblight.putFloat( -h ).putFloat( w ).putFloat( 0.0f )
.putFloat( -.707f ).putFloat( -.707f ).putFloat( .707f );
vblight.putFloat( -h ).putFloat( h ).putFloat( 0.0f )
.putFloat( -.707f ).putFloat( .707f ).putFloat( .707f );
vblight.putFloat( w ).putFloat( w ).putFloat( 0.0f )
.putFloat( .707f ).putFloat( -.707f ).putFloat( .707f );
vblight.putFloat( w ).putFloat( h ).putFloat( 0.0f )
.putFloat( .707f ).putFloat( .707f ).putFloat( .707f );
vblight.clear();
// Create a texture to render
IDirect3DTexture9 tex = new IDirect3DTexture9();
// Change this to put another texture in
// I used an absolute path because it was easier
r = D3DX9.D3DXCreateTextureFromFile( dev,
"E:/My Documents/lwjgl-d3d/lwjgl1.1.4-d3d/LWJGL/res/appletlogo.png",
tex );
if( D3D9.FAILED( r ) ) {
throw new RuntimeException( "Unable to create texture because: " + r );
}
// Create the box with texture coordinates
ByteBuffer vbtex = BufferUtils.createByteBuffer( 80 );
vbtex.putFloat( w ).putFloat( -h ).putFloat( 0.0f )
.putFloat( 0f ).putFloat( 1f );
vbtex.putFloat( w ).putFloat( w ).putFloat( 0.0f )
.putFloat( 0f ).putFloat( 0f );
vbtex.putFloat( h ).putFloat( -h ).putFloat( 0.0f )
.putFloat( 1f ).putFloat( 1f );
vbtex.putFloat( h ).putFloat( w ).putFloat( 0.0f )
.putFloat( 1f ).putFloat( 0f );
vbtex.clear();
dev.ShowCursor( true );
dev.SetCursorPosition( 0, 0, 1 );
D3DXMATRIX camera = new D3DXMATRIX();
D3DX9.D3DXMatrixIdentity( camera );
dev.SetTransform( D3DTRANSFORMSTATETYPE.D3DTS_WORLD, camera );
D3DX9.D3DXMatrixPerspectiveFovLH( camera,
D3DX9.D3DX_PI / 4,
4f / 3f,
1,
1000 );
dev.SetTransform( D3DTRANSFORMSTATETYPE.D3DTS_PROJECTION, camera );
D3DX9.D3DXMatrixLookAtLH( camera,
new D3DXVECTOR3( 1, 1, -1 ),
new D3DXVECTOR3(), new D3DXVECTOR3( 0, 1, 0 ) );
dev.SetTransform( D3DTRANSFORMSTATETYPE.D3DTS_VIEW, camera );
long start = System.currentTimeMillis();
int frames = 0;
while( dev.TestCooperativeLevel() == D3D9.D3D_OK ) {//while everything is OK
dev.BeginScene();
dev.Clear( 0,
null,
D3D9.D3DCLEAR_TARGET | D3D9.D3DCLEAR_ZBUFFER,
color,
1f,
0 );
dev.SetRenderState( D3DRENDERSTATETYPE.D3DRS_LIGHTING, false );
dev.SetFVF( D3D9.D3DFVF_XYZ | D3D9.D3DFVF_DIFFUSE );
// Draw the first box
dev.DrawPrimitiveUP( D3DPRIMITIVETYPE.D3DPT_TRIANGLESTRIP, 2, bb, 16 );
// Draw the vertex buffer box
dev.SetStreamSource( 0, vb, 0, 16 );
dev.DrawPrimitive( D3DPRIMITIVETYPE.D3DPT_TRIANGLESTRIP, 0, 2 );
// Draw the light box
dev.SetRenderState( D3DRENDERSTATETYPE.D3DRS_LIGHTING, true );
dev.SetFVF( D3D9.D3DFVF_XYZ | D3D9.D3DFVF_NORMAL );
dev.DrawPrimitiveUP( D3DPRIMITIVETYPE.D3DPT_TRIANGLESTRIP,
2,
vblight,
24 );
// Draw the texture box
dev.SetRenderState( D3DRENDERSTATETYPE.D3DRS_LIGHTING, false );
dev.SetFVF( D3D9.D3DFVF_XYZ | D3D9.D3DFVF_TEX1 );
dev.SetTexture( 0, tex );
dev.DrawPrimitiveUP( D3DPRIMITIVETYPE.D3DPT_TRIANGLESTRIP,
2,
vbtex,
20 );
dev.SetTexture( 0, null );
dev.EndScene();
dev.Present( null, null, null, null ); // Display what was just rendered
frames++;
// Do some basic FPS calulations
if( System.currentTimeMillis() - start > 1000 ) {
start = System.currentTimeMillis();
f.setTitle( "FPS: " + Integer.toString( frames ) );
frames = 0;
}
}
// Clean up if there is a problem
vb.Release();
dev.Release();
}
}