🔒 Locked
DirectX-based OGL implementation?
Advertisement
Original Post
I know this approaches heresy, to some [grin], but I'm wondering if anyone knows of an implementation of basic OGL (simple matrix and primitive drawing ops, lots of lines, etc) that actually uses DirectX to render (similar to what Vista was going to do). If your wondering, I have a very, very large codebase in GL, but almost everything it does is lines and that sort of thing. I'd like to be able to use it in a DX app without rewriting tens of thousands of lines of gl calls.
Quote:
Original post by Mushu
Wait, so you're looking for a wrapper which converts OpenGL calls to their D3D equivalents? [wow]
Yes. [embarrass]
It is a very, very, large codebase, but doesn't do anything too complicated. It probably does occasionally manipulates the viewport, pushes/pops the matrix stack, does some translating and rotation... lots of ortho stuff with many lines.
I can't talk too much about it, unfortunately, but it's used to render the avionics on a digital display in a cockpit. It's very big and complicated, so I don't want to have to recode it. The drawing is very unfortunately tightly coupled with the logic, so it would essentially be a rewrite (which is out of the question).
I thought about coding it myself, but I thought that someone here may know of a decent one. I'll check out that link, thanks!
Ehm. I guess I wrote the linked article.
I've written a much better version of that code since. The current one is much faster, and costs very little apart from the repeated function calls. It's in MDX rather than native D3D, but a backport to C++ should be trivial. It's not complex code.
Significant differences from the original:
* No reallocation of memory, either system or video
* Uses a single dynamic VB. No UP calls.
* Tweakable buffer size.
* Handles any primitive count, regardless of buffer size.
I've written a much better version of that code since. The current one is much faster, and costs very little apart from the repeated function calls. It's in MDX rather than native D3D, but a backport to C++ should be trivial. It's not complex code.
using System;using System.Collections.Generic;using System.Runtime.InteropServices;using Microsoft.DirectX;using Microsoft.DirectX.Direct3D;using Microsoft.DirectX.Generic;namespace Inductor{ internal class VertexStreamer : IDisposable { [StructLayout( LayoutKind.Sequential, Pack = 4 )] private struct VertexData { public float X, Y, Z; public float Nx, Ny, Nz; public int ColorValue; public float U, V; public const VertexFormats Format = VertexFormats.PositionNormal | VertexFormats.Diffuse | VertexFormats.Texture1; public static int StrideSize { get { return Marshal.SizeOf( typeof( VertexData ) ); } } }; private Device m_Device; private VertexBuffer m_Vb; private VertexData[] m_Vertices; private bool m_Rendering = false; private PrimitiveType m_PrimitiveType = PrimitiveType.PointList; private int m_VertexCount; public VertexStreamer( Device device ) : this( device, 3000 ) { } public VertexStreamer( Device device, int bufferSize ) { if( device == null ) throw new ArgumentNullException( "device" ); if( bufferSize < 3 ) throw new ArgumentOutOfRangeException( "initialSize", bufferSize, "Buffer size must be at least 3." ); m_Vertices = new VertexData[bufferSize]; m_Device = device; m_Vb = new VertexBuffer( device, bufferSize * VertexData.StrideSize, Usage.Dynamic | Usage.WriteOnly, VertexData.Format, Pool.Default, null ); } #region Private Utility Functions private static int ComputePrimitiveCount( PrimitiveType primitiveType, int vertexCount ) { switch( primitiveType ) { case PrimitiveType.PointList: return vertexCount; case PrimitiveType.LineList: return vertexCount / 2; case PrimitiveType.LineStrip: return vertexCount - 1; case PrimitiveType.TriangleList: return vertexCount / 3; case PrimitiveType.TriangleStrip: case PrimitiveType.TriangleFan: return vertexCount - 2; default: return 0; } } private void RestartRendering() { //render what we've got so far End(); //we may need to re-issue certain vertices int[] v = { -1, -1 }; switch( m_PrimitiveType ) { case PrimitiveType.LineStrip: //re-issue the last vertex v[0] = m_VertexCount - 1; break; case PrimitiveType.LineList: //re-issue the last vertex if our size is odd if( m_VertexCount % 2 == 1 ) v[0] = m_VertexCount - 1; break; case PrimitiveType.TriangleList: //re-issue the last 1 or 2 left-over vertices for( int i = 0; i < m_VertexCount % 3; ++i ) { v = m_VertexCount - 2 + i; } break; case PrimitiveType.TriangleStrip: //re-issue the last two vertices v[0] = m_VertexCount - 2; v[1] = m_VertexCount - 1; break; case PrimitiveType.TriangleFan: //re-issue the first and last vertices v[0] = 0; v[1] = m_VertexCount - 1; break; } //now actually submit the new vertices Begin( m_PrimitiveType ); foreach( int i in v ) { if( i > -1 ) { Normal( m_Vertices.Nx, m_Vertices.Ny, m_Vertices.Nz ); Color( m_Vertices.ColorValue ); TexCoord( m_Vertices.U, m_Vertices.V ); Vertex( m_Vertices.X, m_Vertices.Y, m_Vertices.Z ); } } } #endregion public void Begin( PrimitiveType primitiveType ) { if( m_Rendering ) throw new InvalidCallException( "VertexStreamer.Begin() called multiple times." ); //set up a new state m_PrimitiveType = primitiveType; m_VertexCount = 0; m_Rendering = true; } public void Color( int colorValue ) { if( !m_Rendering ) throw new InvalidCallException( "VertexStreamer.Color() called outside of Begin/End pair." ); m_Vertices[m_VertexCount].ColorValue = colorValue; } public void Color( System.Drawing.Color color ) { Color( color.ToArgb() ); } public void Normal( float nx, float ny, float nz ) { if( !m_Rendering ) throw new InvalidCallException( "VertexStreamer.Normal() called outside of Begin/End pair." ); m_Vertices[m_VertexCount].Nx = nx; m_Vertices[m_VertexCount].Ny = ny; m_Vertices[m_VertexCount].Nz = nz; } public void Normal( Vector3 normal ) { Normal( normal.X, normal.Y, normal.Z ); } public void TexCoord( float tu, float tv ) { if( !m_Rendering ) throw new InvalidCallException( "VertexStreamer.TexCoord() called outside of Begin/End pair." ); m_Vertices[m_VertexCount].U = tu; m_Vertices[m_VertexCount].V = tv; } public void Vertex( float x, float y, float z ) { if( !m_Rendering ) throw new InvalidCallException( "VertexStreamer.Vertex() called outside of Begin/End pair." ); m_Vertices[m_VertexCount].X = x; m_Vertices[m_VertexCount].Y = y; m_Vertices[m_VertexCount].Z = z; ++m_VertexCount; if( m_VertexCount == m_Vertices.Length ) RestartRendering(); } public void Vertex( Vector3 position ) { Vertex( position.X, position.Y, position.Z ); } public void End() { if( !m_Rendering ) throw new InvalidCallException( "VertexStreamer.End() called without matching Begin()." ); GraphicsBuffer<VertexData> stream = m_Vb.Lock<VertexData>( 0, 0, LockFlags.Discard ); stream.Write( m_Vertices ); m_Vb.Unlock(); //set up critical device states m_Device.VertexFormat = VertexData.Format; m_Device.SetStreamSource( 0, m_Vb, 0, VertexData.StrideSize ); //Get the correct primitive count and issue a draw call m_Device.DrawPrimitives( m_PrimitiveType, 0, ComputePrimitiveCount( m_PrimitiveType, m_VertexCount ) ); //we're done now m_Rendering = false; } #region IDisposable Members public void Dispose() { m_Vb.Dispose(); } #endregion }}Significant differences from the original:
* No reallocation of memory, either system or video
* Uses a single dynamic VB. No UP calls.
* Tweakable buffer size.
* Handles any primitive count, regardless of buffer size.
Promit, your stuff looks really cool, actually, and I'll probably play with it a bit for my own use. But I really "need" (I use that word loosely... this is an experimental idea I'm working with) something that will simply replace the current GL libs with one that renders using DX so that I don't have to change any code.
Unfortunately, nothing with this code is trivial. Some of it dates back 15 years or more, and it's written in the nastiest, most stereotypically hideous flavor of straight C you can imagine [sick]... enormous static data structures shared by 20 or 30 different components, etc... there are something like 5000 calls to glBegin, a couple of thousand glTranslate calls etc.
But, since it is primarily just a handful of functions that it uses, maybe I can implement those myself.
Unfortunately, nothing with this code is trivial. Some of it dates back 15 years or more, and it's written in the nastiest, most stereotypically hideous flavor of straight C you can imagine [sick]... enormous static data structures shared by 20 or 30 different components, etc... there are something like 5000 calls to glBegin, a couple of thousand glTranslate calls etc.
But, since it is primarily just a handful of functions that it uses, maybe I can implement those myself.
Well, now is probably a good time to point out ID3DXMatrixStack.
So if you need this in D3D, your only option is to write this layer yourself. If the variety in calls is as minimal as you make it sound, then you're going to need the following:
A static device pointer
A static matrix stack pointer
A stack vertex streamer pointer (assuming you implement it as a C++ class)
Then you actually need to rewrite the calls. A couple things to make note of:
You are going to have to switch the front face for D3D; the opposite is default for the two APIs.
You will want to set up an RH projection matrix, presumably via D3DXMatrixLookAtRH.
Probably more stuff I forgot.
Rewriting mine as OpenGL calls is going to be fairly easy. Either do it as a class and give the calls a file scope pointer, or just pull everything out and make it all file scope. Or if you really, really want to bootstrap this quickly, you can use the older version -- I've used that code to port OpenGL apps quick and dirty before. Then you can alter the internal implementation to the new version after it all works.
So if you need this in D3D, your only option is to write this layer yourself. If the variety in calls is as minimal as you make it sound, then you're going to need the following:
A static device pointer
A static matrix stack pointer
A stack vertex streamer pointer (assuming you implement it as a C++ class)
Then you actually need to rewrite the calls. A couple things to make note of:
You are going to have to switch the front face for D3D; the opposite is default for the two APIs.
You will want to set up an RH projection matrix, presumably via D3DXMatrixLookAtRH.
Probably more stuff I forgot.
Rewriting mine as OpenGL calls is going to be fairly easy. Either do it as a class and give the calls a file scope pointer, or just pull everything out and make it all file scope. Or if you really, really want to bootstrap this quickly, you can use the older version -- I've used that code to port OpenGL apps quick and dirty before. Then you can alter the internal implementation to the new version after it all works.
By the sounds of it the system you already have is working and has been working for a long time ...why now would you want to port the rendering over to DirectX?
It sounds like it would be a lot easier to build on top of the legacy code and continue to use OpenGL or throw the whole thing away and start from scratch.
Basically, I am just curious why you'd want to change APIs now [smile]
Regards,
ViLiO
It sounds like it would be a lot easier to build on top of the legacy code and continue to use OpenGL or throw the whole thing away and start from scratch.
Basically, I am just curious why you'd want to change APIs now [smile]
Regards,
ViLiO
Quote:
Original post by ViLiO
Basically, I am just curious why you'd want to change APIs now [smile]
Well, what we have, essentially, is a simulator... which, of course, is much, much more than the graphics (unfortunately, though, the two are nearly inseperable in this case). What some people are becoming more interested in is the application of video game technology to simulation and vice versa.
Some of us were thinking it might be cool to prototype something that might run on the XB360. A first step (in the early phases) would be coercing the old code to run DX without going to the trouble of rewriting any of it... especially since a lot of this will be done just in spare time (to the extent that we actually have any).
Quote:A word of warning -- a reimplementation in DX for Xbox will be much more difficult than a reimplementation for PC, given what you've said so far.
Original post by smitty1276
Some of us were thinking it might be cool to prototype something that might run on the XB360. A first step (in the early phases) would be coercing the old code to run DX without going to the trouble of rewriting any of it... especially since a lot of this will be done just in spare time (to the extent that we actually have any).
Yeah... the thinking here is that we prototype it on PC. If anybody's interested, we can take care of the more difficult stuff later.
Sounds like a rewrite of the rendering code is in order anyway. Using glBegin, etc. to render in is pretty slow even in OpenGL. You'll certainly want to redo all that if it's going to appear on the XBox. Might as well do it now and save yourself the hassle of doing an OpenGL wrapper. :)
Topic Locked
This topic has been locked by a moderator. New replies are not allowed.
Sign in to reply to this topic.
Advertisement