org.lwjgl.d3d Progress / Thoughts

Started by gaarazero, March 13, 2008, 18:07:42

Previous topic - Next topic

gaarazero

Quote from: gaarazero on March 25, 2008, 04:33:27
And yes, D3D9 and D3D10 are quite dissimilar.  Separating them would be a good idea.

After looking over the DirectX 10 API, there is a need to separate them.  All the DirectX 10 interfaces, enums, structures, functions, etc. start with either D3D10, D3DX10, or ID3D10.  From what I can tell, there is no overlap in code (except for ID3DXMatrixStack, which is most likely a typo on their part).  Therefore, keeping the package structure the same (org.lwjgl.d3d) is fine.  The only thing that I can see changing is the D3D class I created, renaming it to D3D9 so later on there can be a class called D3D10.

-gz
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

elias

but having seperate packages (d3d9 and d3d10) will allow a user to cut out the unwanted APIs more easily. For example, I could imagine that most OpenGL games don't want either of the d3d apis, but more importantly, I don't think most d3d9 games want d3d10 and vice versa.

- elias

princec

I don't even know if they can actually be mixed in the same application anyway. Or if they can I bet it's rather buggy.

Cas :)

gaarazero

Quote from: elias on March 28, 2008, 09:03:27
but having seperate packages (d3d9 and d3d10) will allow a user to cut out the unwanted APIs more easily.
True, but then why is GL11, GL12, etc. in the same org.lwjgl.opengl packaged?  What if I am using an on board graphics card that only supports up to GL12?  GL20 is still included in the package, even though I can't use it.

Quote from: elias on March 28, 2008, 09:03:27
For example, I could imagine that most OpenGL games don't want either of the d3d apis, but more importantly, I don't think most d3d9 games want d3d10 and vice versa.
That's why I split this off into it's own jar and dll.  There's no need to include the D3D code if you're just using OpenGL.  I'd like to also not include OpenGL if you're just using D3D.  But that might not be possible, unless some of the more general classes are split into a "core" jar.

Quote from: princec on March 28, 2008, 11:20:37
I don't even know if they can actually be mixed in the same application anyway. Or if they can I bet it's rather buggy.
I'd still want to try :P.
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

elias

Quote from: gaarazero on March 29, 2008, 04:52:56

True, but then why is GL11, GL12, etc. in the same org.lwjgl.opengl packaged?  What if I am using an on board graphics card that only supports up to GL12?  GL20 is still included in the package, even though I can't use it.


GL11 and GL12 (and the rest of opengl) can easily be mixed in the same context, assuming driver support. As far as I understand it, d3d9 and d3d10 can't be used at the same time, but you have to conditionally decide which kind of d3d you want and create a context accordingly (and create two rendering paths). The same thing will happen with gl3, which can't be shared with gl2 (easily). And you're right, we probably want to split out gl2 in a seperate jar (and dll?) as soon as d3d is implemented.

gaarazero

Here are two screenshots I took.

The first describes what methods I used to render the four boxes.

The second is the same as the first, except I changed the PresentationInterval from D3DPRESENT_INTERVAL_ONE to D3DPRESENT_INTERVAL_IMMEDIATE, basically a speed test.

I think if I was using a native display, I could get a few more FPS out of it, but it works so I'm not complaining.  The only thing I will complain about is the way D3D locks it's vertex/index buffers.  The way I would have to do it would be to create a new direct buffer every time around the area that is returned.  That would be fine, except for the fact that when doing things like animation, you call Lock every frame.  I guess that's what garbage collectors are for, but still, that's a lot of buffers.  The way I did it for now is to just set the data to the buffer that's passed in (a memcpy to be precise).  I have an idea on how to fix this to give it more of a 1:1 feel, but I'm not sure if it will work.

-gz
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

gaarazero

I was about to post a pre alpha, but when I tested it on another computer, I was missing a dll.  I got the latest version of the DirectX SDK and doing so means that they updated the d3dx9 dll to the next version, d3dx9_36.dll.  If you have the d3dx9_36.dll, you're all set; if not, go here to download it and place it in the windows native directory where all the lwjgl dlls are.  This is much safer than putting it in your system32 folder.  I've also attached the source code that made the screenshots I posted earlier.  Note: this is in no way finalized or anywhere near complete, it's just a taste of D3D.  One word of advice, don't use D3DPRESENT_INTERVAL_IMMEDIATE; it works, but locks your system for a bit.

I'd like any feedback you guys come up with.

To install, put lwjgl-d3d.dll in the windows native folder and lwjgl_d3d.jar in the jar folder of your lwjgl directory.  I'm going off the 1.1.4 code base.  It works under Java 1.4.  Sorry, Windows only... for now ;).

D3DTest.java
package org.lwjgl.test.d3d;

import java.awt.BorderLayout;
import java.nio.ByteBuffer;

import javax.swing.JFrame;

import org.lwjgl.BufferUtils;
import org.lwjgl.d3d.AWTD3DCanvas;
import org.lwjgl.d3d.D3D9;
import org.lwjgl.d3d.D3DCOLORVALUE;
import org.lwjgl.d3d.D3DDEVTYPE;
import org.lwjgl.d3d.D3DDISPLAYMODE;
import org.lwjgl.d3d.D3DFORMAT;
import org.lwjgl.d3d.D3DLIGHT9;
import org.lwjgl.d3d.D3DMATERIAL9;
import org.lwjgl.d3d.D3DPRESENT_PARAMETERS;
import org.lwjgl.d3d.D3DRENDERSTATETYPE;
import org.lwjgl.d3d.D3DVIEWPORT9;
import org.lwjgl.d3d.D3DX9;
import org.lwjgl.d3d.IDirect3D9;
import org.lwjgl.d3d.IDirect3DDevice9;
import org.lwjgl.d3d.IDirect3DTexture9;
import org.lwjgl.d3d.IDirect3DVertexBuffer9;

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 = D3D9.D3DMULTISAMPLE_NONE;
		m_d3dpp.hDeviceWindow = can.getHWnd();
		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 = D3D9.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 ) ) {
			throw new RuntimeException( "Unable to create device" );
		}

		
		D3DCOLORVALUE color = new D3DCOLORVALUE( .2f, .1f, .6f, 1f ), cc = new D3DCOLORVALUE( 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, D3D9.D3DPOOL_MANAGED, vb, 0L );
		if( D3D9.FAILED( r ) ) {
			throw new RuntimeException( "" + r );
		}
		
		// Set the vertex buffers data
		ByteBuffer vbb = BufferUtils.createByteBuffer( 64 );
		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();

		// This is what it SHOULD look like
		//if( D3D9.SUCCEEDED( vb.Lock( 0, 0, bb, 0 ) ) ) {
			//bb.put( vbb );
			//bb.rewind();
		//	vb.Unlock();
		//}

		// This is how it's done for now
		vb.Lock( 0, 0, vbb, 0 );
		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();

		// By default Lighting is enabled
		dev.SetRenderState( D3DRENDERSTATETYPE.D3DRS_LIGHTING, false );

		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( D3D9.D3DPT_TRIANGLESTRIP, 2, bb, 16 );
			
			// Draw the vertex buffer box
			dev.SetStreamSource( 0, vb, 0, 16 );
			dev.DrawPrimitive( D3D9.D3DPT_TRIANGLESTRIP, 0, 2 );

			// Draw the light box
			dev.SetRenderState( D3DRENDERSTATETYPE.D3DRS_LIGHTING, true );
			dev.SetFVF( D3D9.D3DFVF_XYZ | D3D9.D3DFVF_NORMAL );
			dev.DrawPrimitiveUP( D3D9.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( D3D9.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();
	}

}


-gz
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

Matzon

oh, excellent - when running right now I get this:

Quotejava -cp bin;lwjgl_d3d_pre_alpha\lwjgl_d3d.jar; -Djava.library.path=libs\win32 org.lwjgl.test.d3d.D3DTest
Exception in thread "main" java.lang.UnsatisfiedLinkError: libs\win32\lwjgl-d3d.dll: Can't find dependent libraries
        at java.lang.ClassLoader$NativeLibrary.load(Native Method)
        at java.lang.ClassLoader.loadLibrary0(Unknown Source)
        at java.lang.ClassLoader.loadLibrary(Unknown Source)
        at java.lang.Runtime.loadLibrary0(Unknown Source)
        at java.lang.System.loadLibrary(Unknown Source)
        at org.lwjgl.d3d.D3D9.<clinit>(D3D9.java:10)
        at org.lwjgl.test.d3d.D3DTest.main(D3DTest.java:30)

I have lwjgl_d3d.jar in the classpath and the lwjgl-d3d.dll and d3dx10_36.dll in the native folder. Not entirely sure what I am missing (dx installed).

gaarazero

Quote from: Matzon on April 10, 2008, 06:43:40
I have lwjgl_d3d.jar in the classpath and the lwjgl-d3d.dll and d3dx10_36.dll in the native folder. Not entirely sure what I am missing (dx installed).

It's d3dx9_36.dll :P.
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

Matzon

doh! - same error tho :(

When opening lwjgl-d3d in Dependency Walker, I get the following log:
QuoteError: At least one required implicit or forwarded dependency was not found.
Warning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.
Files marked as red:
JAWT.DLL
DWMAPI.DLL
when I open the lwjgl on I get:
QuoteWarning: At least one delay-load dependency module was not found.
Warning: At least one module has an unresolved import due to a missing export function in a delay-load dependent module.

Files marked as red:
JAWT.DLL
DWMAPI.DLL

gaarazero

Hmmm... I just ran it from another computer with the command
java -cp lwjgl/jar/lwjgl_d3d.jar;bin -Djava.library.path=lwjgl/native test.TestD3D
and got
QuoteThis application has failed to start because jawt.dll was not found. Re-installing the application may fix this problem.
and then the exception.

I was testing it in Eclipse.  I don't know if that makes a difference.
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

Matzon

try compiling with /DELAYLOAD:jawt.dll - thats what we do with lwjgl.dll

gaarazero

Well then, I got it run in a command line.

"C:\Program Files\Java\j2re1.4.2_17\bin\java.exe" -cp bin;lwjgl/jar/lwjgl_d3d.jar;lwjgl/jar/lwjgl.jar -Djava.library.path=lwjgl/native test.TestD3D


Change the path to be the absolute path to your java.exe and it should work.  Yeah Windows...!

-gz
JNewton 0.8 - Newton Dynamics wrapper for Java!
org.lwjgl.d3d - Currently Working On

Matzon

Right that works  ::)
I then changed that path to the texture to my local copy.

Frame opened up - but was grey.
I got the following error:
QuoteException in thread "main" java.lang.UnsatisfiedLinkError: org.lwjgl.d3d.IDirect3DVertexBuffer9.nRelease(J)V
        at org.lwjgl.d3d.IDirect3DVertexBuffer9.nRelease(Native Method)
        at org.lwjgl.d3d.IDirect3DVertexBuffer9.Release(IDirect3DVertexBuffer9.j
ava:48)
        at org.lwjgl.test.d3d.D3DTest.main(D3DTest.java:223)
but since this is in the exit code, that still means that the code doesn't run on my end. Indeed commenting the release part out just gave me the same blank screen.

Matzon

hang on - I need to test this using 1.1.4 :)