Skip to content

Instantly share code, notes, and snippets.

@questor
Created December 14, 2017 10:34
Show Gist options
  • Save questor/c60074f9b9111caeca32f34354901096 to your computer and use it in GitHub Desktop.
Save questor/c60074f9b9111caeca32f34354901096 to your computer and use it in GitHub Desktop.
opengl-1 emulation layer for direct3d9
#include <xtl.h>
#include <xgraphics.h>
#include <stdio.h>
#include "openGL.h"
extern LPDIRECT3DDEVICE8 D3D_Device;
#define MAX_MAT_STACK_MODV 40
#define MAX_MAT_STACK_PROJ 40
//*************************************************
//>#define DEBUG
#define UNUSED 0
#define DEBUGGER() { int blub = 0; blub = 1/blub; }
//MatrixStack:
float modv_matrix[MAX_MAT_STACK_MODV][16];
char modv_level;
float proj_matrix[MAX_MAT_STACK_PROJ][16];
char proj_level;
float per_matrix[16];
float scr_matrix[16];
int screen_startx;
int screen_starty;
int screen_width;
int screen_height;
int matrix_mode;
//Vertex:
unsigned int clearColor;
int inBeginBlock;
unsigned int globalVertexColor;
//Texturemapping:
static int textureCounter = 0;
static LPDIRECT3DTEXTURE8 pTexture[8];
static int textureSizeX[8], textureSizeY[8];
static int actTexture = 0;
//ScreenResize
float screenResize = 0;
#ifdef DEBUG
int numberTransformedVertexPerFrame;
#endif
//*************************************************
extern "C" {
void identityMatrix(float *m);
void transformVertex(float x, float y, float z, float *dest);
void glScreenResize() {
screenResize -= 10;
if(screenResize == -160)
screenResize = 0;
FILE *fp;
fp = fopen("D:\\options.bin","wb");
if(fp) {
fwrite(&screenResize, sizeof(float), 1, fp);
fclose(fp);
}
}
void glInitEmuLayer() {
modv_level = 0;
proj_level = 0;
inBeginBlock = 0;
identityMatrix(modv_matrix[0]);
identityMatrix(proj_matrix[0]);
D3DXMATRIX temp;
D3DXMatrixIdentity(&temp);
D3D_Device->SetTransform(D3DTS_VIEW, &temp);
D3D_Device->SetTransform(D3DTS_PROJECTION, &temp);
D3D_Device->SetTransform(D3DTS_WORLD, &temp);
FILE *fp;
fp = fopen("D:\\options.bin","rb");
if(fp) {
fread(&screenResize, sizeof(float),1,fp);
fclose(fp);
}
}
void glClearColor(float r, float g, float b, float alpha) {
r *= 255.0f;
g *= 255.0f;
b *= 255.0f;
alpha *= 255.0f;
clearColor = (((int)alpha)<<24) | (((int)r)<<16) | (((int)g)<<8) | ((int)b);
}
void glClear(int mask) {
if(mask != GL_COLOR_BUFFER_BIT)
DEBUGGER();
D3D_Device->Clear(0, NULL, D3DCLEAR_TARGET, clearColor, 0,0);
D3D_Device->SetVertexShader(D3DFVF_DIFFUSE|D3DFVF_XYZRHW);
D3D_Device->SetTexture(0, NULL);
}
void glViewport(int x,int y,int width,int height) {
screen_startx = x;
screen_starty = y;
screen_width = width;
screen_height = height;
}
void glSwapBuffers() {
D3D_Device->Present(NULL, NULL, NULL, NULL);
#ifdef DEBUG
char buffer[1024];
sprintf(buffer, "numberTransformedVertexPerFrame %d\n",numberTransformedVertexPerFrame);
OutputDebugString(buffer);
numberTransformedVertexPerFrame = 0;
#endif
}
void glEnable(int cap) {
switch(cap) {
case GL_LINE_SMOOTH:
D3D_Device->SetRenderState(D3DRS_EDGEANTIALIAS, TRUE);
break;
case GL_BLEND:
D3D_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
break;
case GL_TEXTURE_2D:
D3D_Device->SetVertexShader( D3DFVF_XYZRHW | D3DFVF_TEX0);
//> D3D_Device->SetVertexShader(D3DFVF_DIFFUSE|D3DFVF_XYZRHW);
break;
default:
DEBUGGER();
break;
}
}
void glDisable(int cap) {
switch(cap) {
case GL_BLEND:
D3D_Device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
break;
case GL_LIGHTING:
D3D_Device->SetRenderState(D3DRS_LIGHTING, FALSE);
break;
case GL_CULL_FACE:
D3D_Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
break;
case GL_DEPTH_TEST:
D3D_Device->SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE);
break;
case GL_COLOR_MATERIAL:
break;
case GL_TEXTURE_2D:
D3D_Device->SetTexture( 0, NULL );
D3D_Device->SetVertexShader(D3DFVF_DIFFUSE|D3DFVF_XYZRHW);
break;
default:
DEBUGGER();
break;
}
}
void glLineWidth(float width) {
float fLineWidth = width;
D3D_Device->SetRenderState(D3DRS_LINEWIDTH, *((DWORD*)(&fLineWidth)));
}
void glBlendFunc(int sfactor,int dfactor) {
if(sfactor != GL_SRC_ALPHA)
DEBUGGER();
if(dfactor != GL_ONE)
DEBUGGER();
D3D_Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
D3D_Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
}
void glColor4ub(unsigned char red,unsigned char green,unsigned char blue,unsigned char alpha) {
unsigned int colorToSet = (alpha<<24) | (red<<16) | (green<<8) | blue;
if(inBeginBlock==0) {
//set Color Global
globalVertexColor = colorToSet;
} else {
//set for next vertex
D3D_Device->SetVertexDataColor(D3DVSDE_DIFFUSE, colorToSet);
}
}
void glBegin(int mode) {
switch(mode) {
case GL_TRIANGLE_FAN:
D3D_Device->Begin(D3DPT_TRIANGLEFAN);
break;
case GL_LINE_LOOP:
D3D_Device->Begin(D3DPT_LINELOOP);
break;
case GL_LINES:
D3D_Device->Begin(D3DPT_LINELIST);
break;
case GL_LINE_STRIP:
D3D_Device->Begin(D3DPT_LINESTRIP);
break;
case GL_QUADS:
D3D_Device->Begin(D3DPT_QUADLIST);
break;
default:
DEBUGGER();
break;
}
inBeginBlock++;
D3D_Device->SetVertexDataColor(D3DVSDE_DIFFUSE, globalVertexColor);
}
void glEnd() {
--inBeginBlock;
D3D_Device->End();
}
void glVertex3f(float x,float y,float z) {
float t[4];
transformVertex(x,y,z, t);
D3D_Device->SetVertexData4f(D3DVSDE_VERTEX , t[0], t[1], 1.0f, 1.0f);
}
void glVertex2f(float x,float y) {
float t[4];
transformVertex(x,y,1.0f, t);
D3D_Device->SetVertexData4f(D3DVSDE_VERTEX , t[0], t[1], 1.0f, 1.0f);
}
void glTexCoord2f(float s,float t) {
D3D_Device->SetVertexData2f(D3DVSDE_TEXCOORD0, s * textureSizeX[actTexture],
t * textureSizeY[actTexture] );
}
//*********************************************************************************
// MatrixStuff
//*********************************************************************************
void glMatrixMode(int mode) {
matrix_mode = mode;
}
void glLoadIdentity() {
float *m;
switch(matrix_mode) {
case GL_PROJECTION:
m = proj_matrix[proj_level];
break;
case GL_MODELVIEW:
m = modv_matrix[modv_level];
break;
}
identityMatrix(m);
}
void identityMatrix(float *m) {
for(int i=0;i<16;i++)
m[i] = 0.0;
m[0] = 1;
m[5] = 1;
m[10] = 1;
m[15] = 1;
}
void glMultMatrix(const float *input) {
float result[16];
const float *c;
float *m;
int i,j;
c = input;
switch(matrix_mode) {
case GL_PROJECTION:
m = proj_matrix[proj_level];
break;
case GL_MODELVIEW:
m = modv_matrix[modv_level];
break;
}
for (j=0;j<4;j++) {
result[0+j] = m[0+j]*input[0] + m[4+j]*input[1] + m[8+j]*input[2] + m[12+j]*input[3];
result[4+j] = m[0+j]*input[4] + m[4+j]*input[5] + m[8+j]*input[6] + m[12+j]*input[7];
result[8+j] = m[0+j]*input[8] + m[4+j]*input[9] + m[8+j]*input[10] + m[12+j]*input[11];
result[12+j] = m[0+j]*input[12] + m[4+j]*input[13] + m[8+j]*input[14] + m[12+j]*input[15];
}
for (i=0;i<16;i++) {
m[i] = result[i];
}
}
void copyMatrix(const float* src, float* dst) {
int i;
for (i=0; i < 16; i++)
dst[i] = src[i];
}
void glPushMatrix() {
switch (matrix_mode) {
case GL_MODELVIEW:
if (modv_level >= (MAX_MAT_STACK_MODV - 1))
DEBUGGER();
copyMatrix(modv_matrix[modv_level], modv_matrix[modv_level + 1]);
modv_level++;
break;
case GL_PROJECTION:
if (proj_level >= (MAX_MAT_STACK_PROJ - 1))
DEBUGGER();
copyMatrix(proj_matrix[proj_level], proj_matrix[proj_level + 1]);
proj_level++;
break;
}
}
void glPopMatrix() {
switch (matrix_mode) {
case GL_MODELVIEW:
if (modv_level <= 0)
DEBUGGER();
modv_level--;
break;
case GL_PROJECTION:
if (proj_level <= 0)
DEBUGGER();
proj_level--;
break;
}
}
void glTranslatef(float x,float y,float z) {
float *m;
switch(matrix_mode) {
case GL_PROJECTION:
m = proj_matrix[proj_level];
break;
case GL_MODELVIEW:
m = modv_matrix[modv_level];
break;
}
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12];
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13];
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14];
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15];
}
__forceinline void MatrixMultVector(const float *m, const float *p, float *ret) {
float p0,p1,p2,p3;
p0 = p[0];
p1 = p[1];
p2 = p[2];
p3 = p[3];
ret[0] = m[0] * p0 + m[4] * p1 + m[8] * p2 + m[12] * p3;
ret[1] = m[1] * p0 + m[5] * p1 + m[9] * p2 + m[13] * p3;
ret[2] = m[2] * p0 + m[6] * p1 + m[10] * p2 + m[14] * p3;
ret[3] = m[3] * p0 + m[7] * p1 + m[11] * p2 + m[15] * p3;
}
__forceinline void transformVertex(float x, float y, float z, float *dest) {
float p1[4];
float in1[4];
in1[0] = x;
in1[1] = y;
in1[2] = z;
in1[3] = 1.0f;
#ifdef DEBUG
numberTransformedVertexPerFrame++;
#endif
/** Geometric transform */
float *m;
switch(matrix_mode) {
case GL_PROJECTION:
m = proj_matrix[proj_level];
break;
case GL_MODELVIEW:
m = modv_matrix[modv_level];
break;
}
MatrixMultVector(m, in1, p1); //A*in1 => p1
/** Perspective transform */
MatrixMultVector(per_matrix, p1, in1); //A*p1 => in1
/** Go from 4D back to 3D */
in1[0] = in1[0] / in1[3];
in1[1] = in1[1] / in1[3];
in1[2] = in1[2] / in1[3];
in1[3] = 1.0f;
/** Translate into screen coords */
MatrixMultVector(scr_matrix, in1, dest); //A*in1 => dest
}
void glRotatef(float angle,float x,float y,float z) {
float t[16];
float theta;
theta = (3.1415926 / 180) * angle; //Grad => Rad
identityMatrix(t);
if (z == 1) {
t[0] = cos(theta);
t[4] = -sin(theta);
t[1] = sin(theta);
t[5] = cos(theta);
t[10] = 1;
t[15] = 1;
} else if (y == 1) {
t[0] = cos(theta);
t[2] = -sin(theta);
t[8] = sin(theta);
t[10] = cos(theta);
t[5] = 1;
t[15] = 1;
} else if (x == 1) {
t[5] = cos(theta);
t[6] = sin(theta);
t[9] = -sin(theta);
t[10] = cos(theta);
t[0] = 1;
t[15] = 1;
}
glMultMatrix( t );
}
void glScalef(float x, float y, float z) {
float t[16];
identityMatrix(t);
t[0] = x;
t[5] = y;
t[10] = z;
glMultMatrix(t);
}
void glOrtho(float left,float right,float bottom,float top,float zNear,float zFar) {
float d;
//> float width = right - left - screenResize;
//> float height = top - bottom + screenResize;
float width = right - left;
float height = top - bottom;
d = 32000.0;
identityMatrix(per_matrix);
per_matrix[10] = 0;
per_matrix[11] = (1.0/d);
identityMatrix(scr_matrix);
scr_matrix[0] = ((float)screen_width+screenResize) / width;
scr_matrix[5] = -((float)screen_height+screenResize) / height;
scr_matrix[10] = 0;
scr_matrix[12] = -screenResize/2;
scr_matrix[13] = -screenResize/2;
}
void gluLookAt(float eyex,float eyey,float eyez,
float centerx,float centery,float centerz,
float upx,float upy,float upz) {
float m[16];
float x[3], y[3], z[3];
float mag;
/* Make rotation matrix */
/* Z vector */
z[0] = eyex - centerx;
z[1] = eyey - centery;
z[2] = eyez - centerz;
mag = sqrt(z[0] * z[0] + z[1] * z[1] + z[2] * z[2]);
if (mag) {
z[0] /= mag;
z[1] /= mag;
z[2] /= mag;
}
/* Y vector */
y[0] = upx;
y[1] = upy;
y[2] = upz;
/* X vector = Y cross Z */
x[0] = y[1] * z[2] - y[2] * z[1];
x[1] = -y[0] * z[2] + y[2] * z[0];
x[2] = y[0] * z[1] - y[1] * z[0];
/* Recompute Y = Z cross X */
y[0] = z[1] * x[2] - z[2] * x[1];
y[1] = -z[0] * x[2] + z[2] * x[0];
y[2] = z[0] * x[1] - z[1] * x[0];
mag = sqrt(x[0] * x[0] + x[1] * x[1] + x[2] * x[2]);
if (mag) {
x[0] /= mag;
x[1] /= mag;
x[2] /= mag;
}
mag = sqrt(y[0] * y[0] + y[1] * y[1] + y[2] * y[2]);
if (mag) {
y[0] /= mag;
y[1] /= mag;
y[2] /= mag;
}
#define M(row,col) m[row*4+col]
M(0, 0) = x[0];
M(0, 1) = x[1];
M(0, 2) = x[2];
M(0, 3) = 0.0;
M(1, 0) = y[0];
M(1, 1) = y[1];
M(1, 2) = y[2];
M(1, 3) = 0.0;
M(2, 0) = z[0];
M(2, 1) = z[1];
M(2, 2) = z[2];
M(2, 3) = 0.0;
M(3, 0) = 0.0;
M(3, 1) = 0.0;
M(3, 2) = 0.0;
M(3, 3) = 1.0;
#undef M
glMultMatrix(m);
/* Translate Eye to Origin */
glTranslatef(-eyex, -eyey, -eyez);
}
void gluPerspective(float fovy,float aspect,float zNear,float zFar) {
float half_angle;
float f, height, width;
half_angle = (float)(fovy > 0 ? fovy : 45.0)*3.1415926536 / 360.0;
f = cos(half_angle) / sin(half_angle);
height = 2*zNear/f;
width = height*(aspect > 0?aspect:1.0);
identityMatrix(per_matrix);
per_matrix[10] = 0;
per_matrix[11] = (1.0/zNear);
identityMatrix(scr_matrix);
scr_matrix[0] = ((float)screen_width+screenResize) / width;
scr_matrix[5] = ((float)screen_height+screenResize) / height;
scr_matrix[10] = 0;
//> scr_matrix[12] = screen_startx - screenResize/2 + screen_width/2;
//> scr_matrix[13] = screen_starty - screenResize/2 + screen_height/2;
scr_matrix[12] = screen_startx + screen_width/2;
scr_matrix[13] = screen_starty + screen_height/2;
}
//*********************************************************************************
// Texture-Stuff
//*********************************************************************************
void glGenTextures(int n,int *textures) {
int i;
for(i=0; i<n; i++) {
*(textures++) = textureCounter++;
}
}
void glBindTexture(int target, int texture) {
if(target != GL_TEXTURE_2D)
DEBUGGER();
actTexture = texture;
D3D_Device->SetTexture( 0, pTexture[actTexture] );
D3D_Device->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
D3D_Device->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE );
D3D_Device->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_TEXTURE );
//> D3D_Device->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE );
D3D_Device->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_DISABLE );
}
void glTexParameteri(int target,int pname,int param) {
if(target != GL_TEXTURE_2D)
DEBUGGER();
/* GL_TEXTURE_MAG_FILTER,
GL_LINEAR,
GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST,*/
}
void glDeleteTextures(int n,const int *textures) {
}
void gluBuild2DMipmaps(int target,int components,int width,int height,int format,int type,const void *data) {
if(target != GL_TEXTURE_2D)
DEBUGGER();
int texturePitch = (width+63) & 0xFFFFFFC0; //64-boundary
textureSizeX[actTexture] = width;
textureSizeY[actTexture] = height;
int memSize = texturePitch * height * 4;
D3DFORMAT d3dFormat = D3DFMT_LIN_X8R8G8B8;
void *textureMemory;
pTexture[actTexture] = new D3DTexture();
textureMemory = XPhysicalAlloc(memSize, MAXULONG_PTR, 0, PAGE_READWRITE|PAGE_WRITECOMBINE);
XGSetTextureHeader(width, height, 1, UNUSED, d3dFormat, UNUSED, pTexture[actTexture], 0, texturePitch*4);
pTexture[actTexture]->Register(textureMemory);
D3DLOCKED_RECT lockedrect;
pTexture[actTexture]->LockRect(0,&lockedrect,0,0);
int pitch = lockedrect.Pitch / 4;
int *videoMem = (int*)lockedrect.pBits;
int x,y;
unsigned char *srcTexture = (unsigned char*)data;
for(y=0; y<height; y++) {
int *workingLine = videoMem;
for(x=0; x<width; x++) {
*(workingLine++) = ((*(srcTexture++))<<16) | ((*(srcTexture++))<<8) | (*(srcTexture++));
}
videoMem += pitch;
}
pTexture[actTexture]->UnlockRect(0);
/* GL_RGB,
GL_UNSIGNED_BYTE,*/
}
};
enum {
//MatrixMode
GL_PROJECTION,
GL_MODELVIEW,
//Enable
GL_LINE_SMOOTH,
GL_BLEND,
GL_LIGHTING,
GL_CULL_FACE,
GL_DEPTH_TEST,
GL_COLOR_MATERIAL,
//BindTexture, glTexParameteri, gluBuild2DMipmaps, Enable
GL_TEXTURE_2D,
//gluBuild2DMipmaps
GL_RGB,
GL_UNSIGNED_BYTE,
//TexParameteri
GL_TEXTURE_MAG_FILTER,
GL_LINEAR,
GL_TEXTURE_MIN_FILTER,
GL_LINEAR_MIPMAP_NEAREST,
//glBegin
GL_TRIANGLE_FAN,
GL_LINE_LOOP,
GL_LINES,
GL_LINE_STRIP,
GL_QUADS,
//BlendFunc
GL_SRC_ALPHA,
GL_ONE,
//clear
GL_COLOR_BUFFER_BIT
};
#ifdef __cplusplus
extern "C"
{
#endif
void glScreenResize();
void glInitEmuLayer();
void glSwapBuffers();
void glClearColor(float r, float g, float b, float alpha);
void glViewport(int x, int y, int width, int height);
void glMatrixMode(int mode);
void glLoadIdentity();
void glLineWidth(float width);
void glEnable(int cap);
void glDisable(int cap);
void glBlendFunc(int sfactor, int dfactor);
void glGenTextures(int n, int *textures);
void glBindTexture(int target, int texture);
void glTexParameteri(int target, int pname, int param);
void glDeleteTextures(int n, const int *textures);
void glPushMatrix();
void glClear(int mask);
void glPopMatrix();
void glTranslatef(float x, float y, float z);
void glScalef(float x, float y, float z);
void glColor4ub(unsigned char red, unsigned char green, unsigned char blue, unsigned char alpha);
void glBegin(int mode);
void glVertex3f(float x, float y, float z);
void glVertex2f(float x, float y);
void glEnd();
void glRotatef(float angle, float x, float y, float z);
void glTexCoord2f(float s, float t);
void glOrtho(float left, float right, float bottom, float top, float zNear, float zFar);
void gluLookAt(float eyex,
float eyey,
float eyez,
float centerx,
float centery,
float centerz,
float upx,
float upy,
float upz);
void gluPerspective(float fovy,
float aspect,
float zNear,
float zFar);
void gluBuild2DMipmaps(int target,
int components,
int width,
int height,
int format,
int type,
const void *data);
#ifdef __cplusplus
};
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment