implemented texture raster renderstates

This commit is contained in:
aap 2018-07-02 07:01:34 +02:00
parent e6d01b1159
commit 2cffb3f494
20 changed files with 638 additions and 324 deletions

View File

@ -69,7 +69,14 @@ ImGui_ImplRW_RenderDrawLists(ImDrawData* draw_data)
if(pcmd->UserCallback) if(pcmd->UserCallback)
pcmd->UserCallback(cmd_list, pcmd); pcmd->UserCallback(cmd_list, pcmd);
else{ else{
rw::engine->imtexture = (rw::Texture*)pcmd->TextureId; rw::Texture *tex = (rw::Texture*)pcmd->TextureId;
if(tex && tex->raster){
rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
rw::SetRenderState(rw::TEXTUREADDRESSU, tex->getAddressU());
rw::SetRenderState(rw::TEXTUREADDRESSV, tex->getAddressV());
rw::SetRenderState(rw::TEXTUREFILTER, tex->getFilter());
}else
rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST,
g_vertbuf+vtx_offset, cmd_list->VtxBuffer.Size, g_vertbuf+vtx_offset, cmd_list->VtxBuffer.Size,
cmd_list->IdxBuffer.Data+idx_offset, pcmd->ElemCount); cmd_list->IdxBuffer.Data+idx_offset, pcmd->ElemCount);

View File

@ -543,7 +543,7 @@ rasterFromImage(Raster *raster, Image *image)
} }
} }
int32 inc = image->depth/8; int32 inc = image->bpp;
in = image->pixels; in = image->pixels;
out = raster->lock(0); out = raster->lock(0);
if(pallength) if(pallength)

View File

@ -38,21 +38,32 @@ static VidmemRaster *vidmemRasters;
void addVidmemRaster(Raster *raster); void addVidmemRaster(Raster *raster);
void removeVidmemRaster(Raster *raster); void removeVidmemRaster(Raster *raster);
// cached RW render states struct RwRasterStateCache {
static bool32 vertexAlpha; Raster *raster;
static bool32 textureAlpha; Texture::Addressing addressingU;
static uint32 srcblend, destblend; Texture::Addressing addressingV;
static uint32 zwrite; Texture::FilterMode filter;
static uint32 ztest; };
static uint32 fogenable;
static RGBA fogcolor;
static uint32 cullmode;
static uint32 alphafunc;
static uint32 alpharef;
#define MAXNUMSTAGES 8
// cached RW render states
struct RwStateCache {
bool32 vertexAlpha;
bool32 textureAlpha;
uint32 srcblend, destblend;
uint32 zwrite;
uint32 ztest;
uint32 fogenable;
RGBA fogcolor;
uint32 cullmode;
uint32 alphafunc;
uint32 alpharef;
RwRasterStateCache texstage[MAXNUMSTAGES];
};
static RwStateCache rwStateCache;
#define MAXNUMSTATES (D3DRS_BLENDOPALPHA+1) #define MAXNUMSTATES (D3DRS_BLENDOPALPHA+1)
#define MAXNUMSTAGES 8
#define MAXNUMTEXSTATES (D3DTSS_CONSTANT+1) #define MAXNUMTEXSTATES (D3DTSS_CONSTANT+1)
#define MAXNUMSAMPLERSTATES (D3DSAMP_DMAPOFFSET+1) #define MAXNUMSAMPLERSTATES (D3DSAMP_DMAPOFFSET+1)
@ -77,15 +88,50 @@ static uint32 d3dTextureStageStates[MAXNUMTEXSTATES][MAXNUMSTAGES];
static uint32 d3dSamplerStates[MAXNUMSAMPLERSTATES][MAXNUMSTAGES]; static uint32 d3dSamplerStates[MAXNUMSAMPLERSTATES][MAXNUMSTAGES];
// TODO: not only rasters, make a struct
static Raster *d3dRaster[MAXNUMSTAGES];
static bool validStates[MAXNUMSTATES]; static bool validStates[MAXNUMSTATES];
static bool validTexStates[MAXNUMTEXSTATES]; static bool validTexStates[MAXNUMTEXSTATES];
static D3DMATERIAL9 d3dmaterial; static D3DMATERIAL9 d3dmaterial;
static uint32 blendMap[] = {
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_SRCCOLOR,
D3DBLEND_INVSRCCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA,
D3DBLEND_DESTCOLOR,
D3DBLEND_INVDESTCOLOR,
D3DBLEND_SRCALPHASAT
};
static uint32 alphafuncMap[] = {
D3DCMP_ALWAYS,
D3DCMP_GREATEREQUAL,
D3DCMP_LESS
};
static uint32 cullmodeMap[] = {
D3DCULL_NONE,
D3DCULL_CW,
D3DCULL_CCW
};
// TODO: support mipmaps
static uint32 filterConvMap_NoMIP[] = {
0, D3DTEXF_POINT, D3DTEXF_LINEAR,
D3DTEXF_POINT, D3DTEXF_LINEAR,
D3DTEXF_POINT, D3DTEXF_LINEAR
};
static uint32 addressConvMap[] = {
0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
};
// D3D render state // D3D render state
void void
@ -176,8 +222,16 @@ resetD3d9Device(void)
int32 i; int32 i;
uint32 s, t; uint32 s, t;
for(i = 0; i < MAXNUMSTAGES; i++){ for(i = 0; i < MAXNUMSTAGES; i++){
d3dRaster[i] = nil; Raster *raster = rwStateCache.texstage[i].raster;
d3ddevice->SetTexture(i, nil); if(raster){
D3dRaster *d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
d3ddevice->SetTexture(i, (IDirect3DTexture9*)d3draster->texture);
}else
d3ddevice->SetTexture(i, nil);
setSamplerState(i, D3DSAMP_ADDRESSU, addressConvMap[rwStateCache.texstage[i].addressingU]);
setSamplerState(i, D3DSAMP_ADDRESSV, addressConvMap[rwStateCache.texstage[i].addressingV]);
setSamplerState(i, D3DSAMP_MAGFILTER, filterConvMap_NoMIP[rwStateCache.texstage[i].filter]);
setSamplerState(i, D3DSAMP_MINFILTER, filterConvMap_NoMIP[rwStateCache.texstage[i].filter]);
} }
for(s = 0; s < MAXNUMSTATES; s++) for(s = 0; s < MAXNUMSTATES; s++)
if(validStates[s]) if(validStates[s])
@ -197,146 +251,25 @@ resetD3d9Device(void)
static void static void
setVertexAlpha(bool32 enable) setVertexAlpha(bool32 enable)
{ {
if(vertexAlpha != enable){ if(rwStateCache.vertexAlpha != enable){
if(!textureAlpha){ if(!rwStateCache.textureAlpha){
setRenderState(D3DRS_ALPHABLENDENABLE, enable); setRenderState(D3DRS_ALPHABLENDENABLE, enable);
setRenderState(D3DRS_ALPHATESTENABLE, enable); setRenderState(D3DRS_ALPHATESTENABLE, enable);
} }
vertexAlpha = enable; rwStateCache.vertexAlpha = enable;
} }
} }
static uint32 blendMap[] = {
D3DBLEND_ZERO,
D3DBLEND_ONE,
D3DBLEND_SRCCOLOR,
D3DBLEND_INVSRCCOLOR,
D3DBLEND_SRCALPHA,
D3DBLEND_INVSRCALPHA,
D3DBLEND_DESTALPHA,
D3DBLEND_INVDESTALPHA,
D3DBLEND_DESTCOLOR,
D3DBLEND_INVDESTCOLOR,
D3DBLEND_SRCALPHASAT
};
uint32 alphafuncMap[] = {
D3DCMP_ALWAYS,
D3DCMP_GREATEREQUAL,
D3DCMP_LESS
};
uint32 cullmodeMap[] = {
D3DCULL_NONE,
D3DCULL_CW,
D3DCULL_CCW
};
static void
setRwRenderState(int32 state, uint32 value)
{
uint32 bval = value ? TRUE : FALSE;
switch(state){
case VERTEXALPHA:
setVertexAlpha(bval);
break;
case SRCBLEND:
if(srcblend != value){
srcblend = value;
setRenderState(D3DRS_SRCBLEND, blendMap[value]);
}
break;
case DESTBLEND:
if(destblend != value){
destblend = value;
setRenderState(D3DRS_DESTBLEND, blendMap[value]);
}
break;
case ZTESTENABLE:
if(ztest != bval){
ztest = bval;
setRenderState(D3DRS_ZENABLE, ztest);
}
break;
case ZWRITEENABLE:
if(zwrite != bval){
zwrite = bval;
setRenderState(D3DRS_ZWRITEENABLE, zwrite);
}
break;
case FOGENABLE:
if(fogenable != bval){
fogenable = bval;
setRenderState(D3DRS_FOGENABLE, fogenable);
};
break;
case FOGCOLOR:{
RGBA c;
c.red = value;
c.green = value>>8;
c.blue = value>>16;
c.alpha = value>>24;
if(!equal(fogcolor, c)){
fogcolor = c;
setRenderState(D3DRS_FOGCOLOR, D3DCOLOR_RGBA(c.red, c.green, c.blue, c.alpha));
}} break;
case CULLMODE:
if(cullmode != value){
cullmode = value;
setRenderState(D3DRS_CULLMODE, cullmodeMap[value]);
}
break;
case ALPHATESTFUNC:
if(alphafunc != value){
alphafunc = value;
setRenderState(D3DRS_ALPHAFUNC, alphafuncMap[alphafunc]);
}
break;
case ALPHATESTREF:
if(alpharef != value){
alpharef = value;
setRenderState(D3DRS_ALPHAREF, alpharef);
}
break;
}
}
static uint32
getRwRenderState(int32 state)
{
switch(state){
case VERTEXALPHA:
return vertexAlpha;
case SRCBLEND:
return srcblend;
case DESTBLEND:
return destblend;
case ZTESTENABLE:
return ztest;
case ZWRITEENABLE:
return zwrite;
case FOGENABLE:
return fogenable;
case FOGCOLOR:
return RWRGBAINT(fogcolor.red, fogcolor.green, fogcolor.blue, fogcolor.alpha);
case CULLMODE:
return cullmode;
case ALPHATESTFUNC:
return alphafunc;
case ALPHATESTREF:
return alpharef;
}
return 0;
}
void void
setRasterStage(uint32 stage, Raster *raster) setRasterStage(uint32 stage, Raster *raster)
{ {
bool32 alpha; bool32 alpha;
D3dRaster *d3draster = nil; D3dRaster *d3draster = nil;
if(raster != d3dRaster[stage]){ if(raster != rwStateCache.texstage[stage].raster){
d3dRaster[stage] = raster; rwStateCache.texstage[stage].raster = raster;
if(raster){ if(raster){
assert(raster->platform == PLATFORM_D3D8 ||
raster->platform == PLATFORM_D3D9);
d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset); d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
d3ddevice->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture); d3ddevice->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture);
alpha = d3draster->hasAlpha; alpha = d3draster->hasAlpha;
@ -345,9 +278,9 @@ setRasterStage(uint32 stage, Raster *raster)
alpha = 0; alpha = 0;
} }
if(stage == 0){ if(stage == 0){
if(textureAlpha != alpha){ if(rwStateCache.textureAlpha != alpha){
textureAlpha = alpha; rwStateCache.textureAlpha = alpha;
if(!vertexAlpha){ if(!rwStateCache.vertexAlpha){
setRenderState(D3DRS_ALPHABLENDENABLE, alpha); setRenderState(D3DRS_ALPHABLENDENABLE, alpha);
setRenderState(D3DRS_ALPHATESTENABLE, alpha); setRenderState(D3DRS_ALPHATESTENABLE, alpha);
} }
@ -356,28 +289,46 @@ setRasterStage(uint32 stage, Raster *raster)
} }
} }
static void
setFilterMode(uint32 stage, int32 filter)
{
// TODO: mip mapping
if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){
rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter;
setSamplerState(0, D3DSAMP_MAGFILTER, filterConvMap_NoMIP[filter]);
setSamplerState(0, D3DSAMP_MINFILTER, filterConvMap_NoMIP[filter]);
}
}
static void
setAddressU(uint32 stage, int32 addressing)
{
if(rwStateCache.texstage[stage].addressingU != (Texture::Addressing)addressing){
rwStateCache.texstage[stage].addressingU = (Texture::Addressing)addressing;
setSamplerState(0, D3DSAMP_ADDRESSU, addressConvMap[addressing]);
}
}
static void
setAddressV(uint32 stage, int32 addressing)
{
if(rwStateCache.texstage[stage].addressingV != (Texture::Addressing)addressing){
rwStateCache.texstage[stage].addressingV = (Texture::Addressing)addressing;
setSamplerState(0, D3DSAMP_ADDRESSV, addressConvMap[addressing]);
}
}
void void
setTexture(uint32 stage, Texture *tex) setTexture(uint32 stage, Texture *tex)
{ {
// TODO: support mipmaps
static DWORD filternomip[] = {
0, D3DTEXF_POINT, D3DTEXF_LINEAR,
D3DTEXF_POINT, D3DTEXF_LINEAR,
D3DTEXF_POINT, D3DTEXF_LINEAR
};
static DWORD wrap[] = {
0, D3DTADDRESS_WRAP, D3DTADDRESS_MIRROR,
D3DTADDRESS_CLAMP, D3DTADDRESS_BORDER
};
if(tex == nil){ if(tex == nil){
setRasterStage(stage, nil); setRasterStage(stage, nil);
return; return;
} }
if(tex->raster){ if(tex->raster){
setSamplerState(stage, D3DSAMP_MAGFILTER, filternomip[tex->getFilter()]); setFilterMode(stage, tex->getFilter());
setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->getFilter()]); setAddressU(stage, tex->getAddressU());
setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[tex->getAddressU()]); setAddressV(stage, tex->getAddressV());
setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[tex->getAddressV()]);
} }
setRasterStage(stage, tex->raster); setRasterStage(stage, tex->raster);
} }
@ -428,6 +379,152 @@ setMaterial(SurfaceProperties surfProps, rw::RGBA color)
setD3dMaterial(&mat9); setD3dMaterial(&mat9);
} }
static void
setRwRenderState(int32 state, void *pvalue)
{
uint32 value = (uint32)(uintptr)pvalue;
uint32 bval = value ? TRUE : FALSE;
switch(state){
case TEXTURERASTER:
setRasterStage(0, (Raster*)pvalue);
break;
case TEXTUREADDRESS:
setAddressU(0, value);
setAddressV(0, value);
break;
case TEXTUREADDRESSU:
setAddressU(0, value);
break;
case TEXTUREADDRESSV:
setAddressV(0, value);
break;
case TEXTUREFILTER:
setFilterMode(0, value);
break;
case VERTEXALPHA:
setVertexAlpha(bval);
break;
case SRCBLEND:
if(rwStateCache.srcblend != value){
rwStateCache.srcblend = value;
setRenderState(D3DRS_SRCBLEND, blendMap[value]);
}
break;
case DESTBLEND:
if(rwStateCache.destblend != value){
rwStateCache.destblend = value;
setRenderState(D3DRS_DESTBLEND, blendMap[value]);
}
break;
case ZTESTENABLE:
if(rwStateCache.ztest != bval){
rwStateCache.ztest = bval;
setRenderState(D3DRS_ZENABLE, rwStateCache.ztest);
}
break;
case ZWRITEENABLE:
if(rwStateCache.zwrite != bval){
rwStateCache.zwrite = bval;
setRenderState(D3DRS_ZWRITEENABLE, rwStateCache.zwrite);
}
break;
case FOGENABLE:
if(rwStateCache.fogenable != bval){
rwStateCache.fogenable = bval;
setRenderState(D3DRS_FOGENABLE, rwStateCache.fogenable);
};
break;
case FOGCOLOR:{
RGBA c;
c.red = value;
c.green = value>>8;
c.blue = value>>16;
c.alpha = value>>24;
if(!equal(rwStateCache.fogcolor, c)){
rwStateCache.fogcolor = c;
setRenderState(D3DRS_FOGCOLOR, D3DCOLOR_RGBA(c.red, c.green, c.blue, c.alpha));
}} break;
case CULLMODE:
if(rwStateCache.cullmode != value){
rwStateCache.cullmode = value;
setRenderState(D3DRS_CULLMODE, cullmodeMap[value]);
}
break;
case ALPHATESTFUNC:
if(rwStateCache.alphafunc != value){
rwStateCache.alphafunc = value;
setRenderState(D3DRS_ALPHAFUNC, alphafuncMap[rwStateCache.alphafunc]);
}
break;
case ALPHATESTREF:
if(rwStateCache.alpharef != value){
rwStateCache.alpharef = value;
setRenderState(D3DRS_ALPHAREF, rwStateCache.alpharef);
}
break;
}
}
static void*
getRwRenderState(int32 state)
{
uint32 val;
switch(state){
case TEXTURERASTER:
return rwStateCache.texstage[0].raster;
case TEXTUREADDRESS:
if(rwStateCache.texstage[0].addressingU == rwStateCache.texstage[0].addressingV)
val = rwStateCache.texstage[0].addressingU;
else
val = 0; // invalid
break;
case TEXTUREADDRESSU:
val = rwStateCache.texstage[0].addressingU;
break;
case TEXTUREADDRESSV:
val = rwStateCache.texstage[0].addressingV;
break;
case TEXTUREFILTER:
val = rwStateCache.texstage[0].filter;
break;
case VERTEXALPHA:
val = rwStateCache.vertexAlpha;
break;
case SRCBLEND:
val = rwStateCache.srcblend;
break;
case DESTBLEND:
val = rwStateCache.destblend;
break;
case ZTESTENABLE:
val = rwStateCache.ztest;
break;
case ZWRITEENABLE:
val = rwStateCache.zwrite;
break;
case FOGENABLE:
val = rwStateCache.fogenable;
break;
case FOGCOLOR:
val = RWRGBAINT(rwStateCache.fogcolor.red, rwStateCache.fogcolor.green,
rwStateCache.fogcolor.blue, rwStateCache.fogcolor.alpha);
break;
case CULLMODE:
val = rwStateCache.cullmode;
break;
case ALPHATESTFUNC:
val = rwStateCache.alphafunc;
break;
case ALPHATESTREF:
val = rwStateCache.alpharef;
break;
default:
val = 0;
}
return (void*)(uintptr)val;
}
// Shaders // Shaders
void void
@ -750,26 +847,26 @@ initD3D(void)
// TODO: do some real stuff here // TODO: do some real stuff here
d3ddevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); d3ddevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
alphafunc = ALPHAGREATEREQUAL; rwStateCache.alphafunc = ALPHAGREATEREQUAL;
d3ddevice->SetRenderState(D3DRS_ALPHAREF, 10); d3ddevice->SetRenderState(D3DRS_ALPHAREF, 10);
alpharef = 10; rwStateCache.alpharef = 10;
d3ddevice->SetRenderState(D3DRS_FOGENABLE, FALSE); d3ddevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
fogenable = 0; rwStateCache.fogenable = 0;
d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR); d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
// TODO: more fog stuff // TODO: more fog stuff
d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
cullmode = CULLNONE; rwStateCache.cullmode = CULLNONE;
d3ddevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); d3ddevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
srcblend = BLENDSRCALPHA; rwStateCache.srcblend = BLENDSRCALPHA;
d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
destblend = BLENDINVSRCALPHA; rwStateCache.destblend = BLENDINVSRCALPHA;
d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 0); d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 0);
vertexAlpha = 0; rwStateCache.vertexAlpha = 0;
textureAlpha = 0; rwStateCache.textureAlpha = 0;
setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
// setTextureStageState(0, D3DTSS_CONSTANT, 0xFFFFFFFF); // setTextureStageState(0, D3DTSS_CONSTANT, 0xFFFFFFFF);

View File

@ -76,7 +76,6 @@ im2DRenderIndexedPrimitive(PrimitiveType primType,
d3ddevice->SetStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex)); d3ddevice->SetStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex));
d3ddevice->SetIndices(im2dindbuf); d3ddevice->SetIndices(im2dindbuf);
d3ddevice->SetVertexDeclaration(im2ddecl); d3ddevice->SetVertexDeclaration(im2ddecl);
d3d::setTexture(0, engine->imtexture);
setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
@ -175,7 +174,6 @@ im3DRenderIndexed(PrimitiveType primType, void *indices, int32 numIndices)
unlockIndices(im3dindbuf); unlockIndices(im3dindbuf);
d3ddevice->SetIndices(im3dindbuf); d3ddevice->SetIndices(im3dindbuf);
d3d::setTexture(0, engine->imtexture);
setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);

View File

@ -112,7 +112,6 @@ Engine::open(void)
engine = (Engine*)rwNew(Engine::s_plglist.size, MEMDUR_GLOBAL); engine = (Engine*)rwNew(Engine::s_plglist.size, MEMDUR_GLOBAL);
engine->currentCamera = nil; engine->currentCamera = nil;
engine->currentWorld = nil; engine->currentWorld = nil;
engine->imtexture = nil;
// Initialize device // Initialize device
// Device and possibly OS specific! // Device and possibly OS specific!
@ -207,8 +206,8 @@ void endUpdate(Camera*) { }
void clearCamera(Camera*,RGBA*,uint32) { } void clearCamera(Camera*,RGBA*,uint32) { }
void showRaster(Raster*) { } void showRaster(Raster*) { }
void setRenderState(int32, uint32) { } void setRenderState(int32, void*) { }
uint32 getRenderState(int32) { return 0; } void *getRenderState(int32) { return 0; }
void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32) { } void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32) { }

View File

@ -1,6 +1,7 @@
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <cstring> #include <cstring>
#include <cassert>
#include "../rwbase.h" #include "../rwbase.h"
#include "../rwerror.h" #include "../rwerror.h"
@ -83,15 +84,28 @@ static bool32 stateDirty = 1;
static bool32 sceneDirty = 1; static bool32 sceneDirty = 1;
static bool32 objectDirty = 1; static bool32 objectDirty = 1;
// cached render states struct RwRasterStateCache {
static bool32 vertexAlpha; Raster *raster;
static uint32 alphaTestEnable; Texture::Addressing addressingU;
static uint32 alphaFunc; Texture::Addressing addressingV;
static bool32 textureAlpha; Texture::FilterMode filter;
static uint32 srcblend, destblend; };
static uint32 zwrite;
static uint32 ztest; #define MAXNUMSTAGES 8
static uint32 cullmode;
// cached RW render states
struct RwStateCache {
bool32 vertexAlpha;
uint32 alphaTestEnable;
uint32 alphaFunc;
bool32 textureAlpha;
uint32 srcblend, destblend;
uint32 zwrite;
uint32 ztest;
uint32 cullmode;
RwRasterStateCache texstage[MAXNUMSTAGES];
};
static RwStateCache rwStateCache;
static int32 activeTexture; static int32 activeTexture;
@ -113,9 +127,9 @@ static void
setAlphaTest(bool32 enable) setAlphaTest(bool32 enable)
{ {
uint32 shaderfunc; uint32 shaderfunc;
if(alphaTestEnable != enable){ if(rwStateCache.alphaTestEnable != enable){
alphaTestEnable = enable; rwStateCache.alphaTestEnable = enable;
shaderfunc = alphaTestEnable ? alphaFunc : ALPHAALWAYS; shaderfunc = rwStateCache.alphaTestEnable ? rwStateCache.alphaFunc : ALPHAALWAYS;
if(uniformState.alphaFunc != shaderfunc){ if(uniformState.alphaFunc != shaderfunc){
uniformState.alphaFunc = shaderfunc; uniformState.alphaFunc = shaderfunc;
stateDirty = 1; stateDirty = 1;
@ -127,9 +141,9 @@ static void
setAlphaTestFunction(uint32 function) setAlphaTestFunction(uint32 function)
{ {
uint32 shaderfunc; uint32 shaderfunc;
if(alphaFunc != function){ if(rwStateCache.alphaFunc != function){
alphaFunc = function; rwStateCache.alphaFunc = function;
shaderfunc = alphaTestEnable ? alphaFunc : ALPHAALWAYS; shaderfunc = rwStateCache.alphaTestEnable ? rwStateCache.alphaFunc : ALPHAALWAYS;
if(uniformState.alphaFunc != shaderfunc){ if(uniformState.alphaFunc != shaderfunc){
uniformState.alphaFunc = shaderfunc; uniformState.alphaFunc = shaderfunc;
stateDirty = 1; stateDirty = 1;
@ -140,47 +154,201 @@ setAlphaTestFunction(uint32 function)
static void static void
setVertexAlpha(bool32 enable) setVertexAlpha(bool32 enable)
{ {
if(vertexAlpha != enable){ if(rwStateCache.vertexAlpha != enable){
if(!textureAlpha){ if(!rwStateCache.textureAlpha){
(enable ? glEnable : glDisable)(GL_BLEND); (enable ? glEnable : glDisable)(GL_BLEND);
setAlphaTest(enable); setAlphaTest(enable);
} }
vertexAlpha = enable; rwStateCache.vertexAlpha = enable;
} }
} }
static void static void
setRenderState(int32 state, uint32 value) setActiveTexture(int32 n)
{ {
if(activeTexture != n){
activeTexture = n;
glActiveTexture(n);
}
}
// TODO: support mipmaps
static GLint filterConvMap_NoMIP[] = {
0, GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR
};
static GLint addressConvMap[] = {
0, GL_REPEAT, GL_MIRRORED_REPEAT,
GL_CLAMP, GL_CLAMP_TO_BORDER
};
static void
setFilterMode(uint32 stage, int32 filter)
{
if(rwStateCache.texstage[stage].filter != (Texture::FilterMode)filter){
rwStateCache.texstage[stage].filter = (Texture::FilterMode)filter;
Raster *raster = rwStateCache.texstage[stage].raster;
if(raster){
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, rwStateCache.texstage[stage].raster, nativeRasterOffset);
if(natras->filterMode != filter){
setActiveTexture(stage);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_NoMIP[filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]);
natras->filterMode = filter;
}
}
}
}
static void
setAddressU(uint32 stage, int32 addressing)
{
if(rwStateCache.texstage[stage].addressingU != (Texture::Addressing)addressing){
rwStateCache.texstage[stage].addressingU = (Texture::Addressing)addressing;
Raster *raster = rwStateCache.texstage[stage].raster;
if(raster){
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
if(natras->addressU == addressing){
setActiveTexture(stage);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, addressConvMap[addressing]);
natras->addressU = addressing;
}
}
}
}
static void
setAddressV(uint32 stage, int32 addressing)
{
if(rwStateCache.texstage[stage].addressingV != (Texture::Addressing)addressing){
rwStateCache.texstage[stage].addressingV = (Texture::Addressing)addressing;
Raster *raster = rwStateCache.texstage[stage].raster;
if(raster){
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, rwStateCache.texstage[stage].raster, nativeRasterOffset);
if(natras->addressV == addressing){
setActiveTexture(stage);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, addressConvMap[addressing]);
natras->addressV = addressing;
}
}
}
}
static void
setRasterStage(uint32 stage, Raster *raster)
{
bool32 alpha;
if(raster != rwStateCache.texstage[stage].raster){
rwStateCache.texstage[stage].raster = raster;
setActiveTexture(GL_TEXTURE0+stage);
if(raster){
assert(raster->platform == PLATFORM_GL3);
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, raster, nativeRasterOffset);
glBindTexture(GL_TEXTURE_2D, natras->texid);
uint32 filter = rwStateCache.texstage[stage].filter;
uint32 addrU = rwStateCache.texstage[stage].addressingU;
uint32 addrV = rwStateCache.texstage[stage].addressingV;
if(natras->filterMode != filter){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filterConvMap_NoMIP[filter]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filterConvMap_NoMIP[filter]);
natras->filterMode = filter;
}
if(natras->addressU != addrU){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, addressConvMap[addrU]);
natras->addressU = addrU;
}
if(natras->addressU != addrV){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, addressConvMap[addrV]);
natras->addressV = addrV;
}
alpha = natras->hasAlpha;
}else{
glBindTexture(GL_TEXTURE_2D, whitetex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
alpha = 0;
}
if(stage == 0){
if(alpha != rwStateCache.textureAlpha){
rwStateCache.textureAlpha = alpha;
if(!rwStateCache.vertexAlpha){
(alpha ? glEnable : glDisable)(GL_BLEND);
setAlphaTest(alpha);
}
}
}
}
}
void
setTexture(int32 stage, Texture *tex)
{
if(tex == nil){
setRasterStage(stage, nil);
return;
}
if(tex->raster){
setFilterMode(stage, tex->getFilter());
setAddressU(stage, tex->getAddressU());
setAddressV(stage, tex->getAddressV());
}
setRasterStage(stage, tex->raster);
}
static void
setRenderState(int32 state, void *pvalue)
{
uint32 value = (uint32)(uintptr)pvalue;
switch(state){ switch(state){
case TEXTURERASTER:
setRasterStage(0, (Raster*)pvalue);
break;
case TEXTUREADDRESS:
setAddressU(0, value);
setAddressV(0, value);
break;
case TEXTUREADDRESSU:
setAddressU(0, value);
break;
case TEXTUREADDRESSV:
setAddressV(0, value);
break;
case TEXTUREFILTER:
setFilterMode(0, value);
break;
case VERTEXALPHA: case VERTEXALPHA:
setVertexAlpha(value); setVertexAlpha(value);
break; break;
case SRCBLEND: case SRCBLEND:
if(srcblend != value){ if(rwStateCache.srcblend != value){
srcblend = value; rwStateCache.srcblend = value;
glBlendFunc(blendMap[srcblend], blendMap[destblend]); glBlendFunc(blendMap[rwStateCache.srcblend], blendMap[rwStateCache.destblend]);
} }
break; break;
case DESTBLEND: case DESTBLEND:
if(destblend != value){ if(rwStateCache.destblend != value){
destblend = value; rwStateCache.destblend = value;
glBlendFunc(blendMap[srcblend], blendMap[destblend]); glBlendFunc(blendMap[rwStateCache.srcblend], blendMap[rwStateCache.destblend]);
} }
break; break;
case ZTESTENABLE: case ZTESTENABLE:
if(ztest != value){ if(rwStateCache.ztest != value){
ztest = value; rwStateCache.ztest = value;
if(ztest) if(rwStateCache.ztest)
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
else else
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
} }
break; break;
case ZWRITEENABLE: case ZWRITEENABLE:
if(zwrite != (value ? GL_TRUE : GL_FALSE)){ if(rwStateCache.zwrite != (value ? GL_TRUE : GL_FALSE)){
zwrite = value ? GL_TRUE : GL_FALSE; rwStateCache.zwrite = value ? GL_TRUE : GL_FALSE;
glDepthMask(zwrite); glDepthMask(rwStateCache.zwrite);
} }
break; break;
case FOGENABLE: case FOGENABLE:
@ -200,13 +368,13 @@ setRenderState(int32 state, uint32 value)
stateDirty = 1; stateDirty = 1;
break; break;
case CULLMODE: case CULLMODE:
if(cullmode != value){ if(rwStateCache.cullmode != value){
cullmode = value; rwStateCache.cullmode = value;
if(cullmode == CULLNONE) if(rwStateCache.cullmode == CULLNONE)
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
else{ else{
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glCullFace(cullmode == CULLBACK ? GL_BACK : GL_FRONT); glCullFace(rwStateCache.cullmode == CULLBACK ? GL_BACK : GL_FRONT);
} }
} }
break; break;
@ -223,41 +391,72 @@ setRenderState(int32 state, uint32 value)
} }
} }
static uint32 static void*
getRenderState(int32 state) getRenderState(int32 state)
{ {
uint32 val;
RGBA rgba; RGBA rgba;
switch(state){ switch(state){
case TEXTURERASTER:
return rwStateCache.texstage[0].raster;
case TEXTUREADDRESS:
if(rwStateCache.texstage[0].addressingU == rwStateCache.texstage[0].addressingV)
val = rwStateCache.texstage[0].addressingU;
else
val = 0; // invalid
break;
case TEXTUREADDRESSU:
val = rwStateCache.texstage[0].addressingU;
break;
case TEXTUREADDRESSV:
val = rwStateCache.texstage[0].addressingV;
break;
case TEXTUREFILTER:
val = rwStateCache.texstage[0].filter;
break;
case VERTEXALPHA: case VERTEXALPHA:
return vertexAlpha; val = rwStateCache.vertexAlpha;
break;
case SRCBLEND: case SRCBLEND:
return srcblend; val = rwStateCache.srcblend;
break;
case DESTBLEND: case DESTBLEND:
return destblend; val = rwStateCache.destblend;
break;
case ZTESTENABLE: case ZTESTENABLE:
return ztest; val = rwStateCache.ztest;
break;
case ZWRITEENABLE: case ZWRITEENABLE:
return zwrite; val = rwStateCache.zwrite;
break;
case FOGENABLE: case FOGENABLE:
return uniformState.fogEnable; val = uniformState.fogEnable;
break;
case FOGCOLOR: case FOGCOLOR:
convColor(&rgba, &uniformState.fogColor); convColor(&rgba, &uniformState.fogColor);
return RWRGBAINT(rgba.red, rgba.green, rgba.blue, rgba.alpha); val = RWRGBAINT(rgba.red, rgba.green, rgba.blue, rgba.alpha);
break;
case CULLMODE: case CULLMODE:
return cullmode; val = rwStateCache.cullmode;
break;
case ALPHATESTFUNC: case ALPHATESTFUNC:
return alphaFunc; val = rwStateCache.alphaFunc;
break;
case ALPHATESTREF: case ALPHATESTREF:
return (uint32)(uniformState.alphaRef*255.0f); val = (uint32)(uniformState.alphaRef*255.0f);
break;
default:
val = 0;
} }
return 0; return (void*)(uintptr)val;
} }
static void static void
resetRenderState(void) resetRenderState(void)
{ {
alphaFunc = ALPHAGREATEREQUAL; rwStateCache.alphaFunc = ALPHAGREATEREQUAL;
uniformState.alphaFunc = 0; uniformState.alphaFunc = 0;
uniformState.alphaRef = 10.0f/255.0f; uniformState.alphaRef = 10.0f/255.0f;
uniformState.fogEnable = 0; uniformState.fogEnable = 0;
@ -265,28 +464,28 @@ resetRenderState(void)
uniformState.fogColor = { 1.0f, 1.0f, 1.0f, 1.0f }; uniformState.fogColor = { 1.0f, 1.0f, 1.0f, 1.0f };
stateDirty = 1; stateDirty = 1;
vertexAlpha = 0; rwStateCache.vertexAlpha = 0;
textureAlpha = 0; rwStateCache.textureAlpha = 0;
glDisable(GL_BLEND); glDisable(GL_BLEND);
alphaTestEnable = 0; rwStateCache.alphaTestEnable = 0;
srcblend = BLENDSRCALPHA; rwStateCache.srcblend = BLENDSRCALPHA;
destblend = BLENDINVSRCALPHA; rwStateCache.destblend = BLENDINVSRCALPHA;
glBlendFunc(blendMap[srcblend], blendMap[destblend]); glBlendFunc(blendMap[rwStateCache.srcblend], blendMap[rwStateCache.destblend]);
zwrite = GL_TRUE; rwStateCache.zwrite = GL_TRUE;
glDepthMask(zwrite); glDepthMask(rwStateCache.zwrite);
ztest = 1; rwStateCache.ztest = 1;
glEnable(GL_DEPTH_TEST); glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL); glDepthFunc(GL_LEQUAL);
cullmode = CULLNONE; rwStateCache.cullmode = CULLNONE;
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
for(int i = 0; i < 8; i++){ for(int i = 0; i < MAXNUMSTAGES; i++){
glActiveTexture(GL_TEXTURE0+i); glActiveTexture(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, whitetex);
} }
} }
@ -347,61 +546,6 @@ setViewMatrix(float32 *mat)
sceneDirty = 1; sceneDirty = 1;
} }
static void
setActiveTexture(int32 n)
{
if(activeTexture != n){
activeTexture = n;
glActiveTexture(n);
}
}
void
setTexture(int32 n, Texture *tex)
{
// TODO: support mipmaps
static GLint filternomip[] = {
0, GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR,
GL_NEAREST, GL_LINEAR
};
static GLint wrap[] = {
0, GL_REPEAT, GL_MIRRORED_REPEAT,
GL_CLAMP, GL_CLAMP_TO_BORDER
};
bool32 alpha;
setActiveTexture(GL_TEXTURE0+n);
if(tex == nil || tex->raster == nil ||
tex->raster->platform != PLATFORM_GL3 ||
tex->raster->width == 0){
glBindTexture(GL_TEXTURE_2D, whitetex);
alpha = 0;
}else{
Gl3Raster *natras = PLUGINOFFSET(Gl3Raster, tex->raster,
nativeRasterOffset);
glBindTexture(GL_TEXTURE_2D, natras->texid);
alpha = natras->hasAlpha;
if(tex->filterAddressing != natras->filterAddressing){
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filternomip[tex->getFilter()]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filternomip[tex->getFilter()]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap[tex->getAddressU()]);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap[tex->getAddressV()]);
natras->filterAddressing = tex->filterAddressing;
}
}
if(n == 0){
if(alpha != textureAlpha){
textureAlpha = alpha;
if(!vertexAlpha){
(alpha ? glEnable : glDisable)(GL_BLEND);
setAlphaTest(alpha);
}
}
}
}
void void
flushCache(void) flushCache(void)
{ {
@ -593,6 +737,14 @@ initOpenGL(void)
glClearColor(0.25, 0.25, 0.25, 1.0); glClearColor(0.25, 0.25, 0.25, 1.0);
byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF};
glGenTextures(1, &whitetex);
glBindTexture(GL_TEXTURE_2D, whitetex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1,
0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel);
resetRenderState(); resetRenderState();
glGenVertexArrays(1, &vao); glGenVertexArrays(1, &vao);
@ -619,14 +771,6 @@ initOpenGL(void)
GL_DYNAMIC_DRAW); GL_DYNAMIC_DRAW);
glBindBuffer(GL_UNIFORM_BUFFER, 0); glBindBuffer(GL_UNIFORM_BUFFER, 0);
byte whitepixel[4] = {0xFF, 0xFF, 0xFF, 0xFF};
glGenTextures(1, &whitetex);
glBindTexture(GL_TEXTURE_2D, whitetex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1,
0, GL_RGBA, GL_UNSIGNED_BYTE, &whitepixel);
#include "shaders/simple_vs_gl3.inc" #include "shaders/simple_vs_gl3.inc"
#include "shaders/simple_fs_gl3.inc" #include "shaders/simple_fs_gl3.inc"
simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src); simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src);

View File

@ -100,7 +100,6 @@ im2DRenderIndexedPrimitive(PrimitiveType primType,
setAttribPointers(im2dattribDesc, 3); setAttribPointers(im2dattribDesc, 3);
glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform); glUniform4fv(currentShader->uniformLocations[u_xform], 1, xform);
setTexture(0, engine->imtexture);
flushCache(); flushCache();
glDrawElements(primTypeMap[primType], numIndices, glDrawElements(primTypeMap[primType], numIndices,
@ -179,8 +178,6 @@ im3DRenderIndexed(PrimitiveType primType, void *indices, int32 numIndices)
glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2, glBufferData(GL_ELEMENT_ARRAY_BUFFER, numIndices*2,
indices, GL_DYNAMIC_DRAW); indices, GL_DYNAMIC_DRAW);
setTexture(0, engine->imtexture);
flushCache(); flushCache();
glDrawElements(primTypeMap[primType], numIndices, glDrawElements(primTypeMap[primType], numIndices,
GL_UNSIGNED_SHORT, nil); GL_UNSIGNED_SHORT, nil);

View File

@ -86,7 +86,9 @@ rasterCreate(Raster *raster)
glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat, glTexImage2D(GL_TEXTURE_2D, 0, natras->internalFormat,
raster->width, raster->height, raster->width, raster->height,
0, natras->format, natras->type, nil); 0, natras->format, natras->type, nil);
natras->filterAddressing = ~0; natras->filterMode = 0;
natras->addressU = 0;
natras->addressV = 0;
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
#endif #endif

View File

@ -172,7 +172,9 @@ struct Gl3Raster
bool32 hasAlpha; bool32 hasAlpha;
// cached filtermode and addressing // cached filtermode and addressing
uint32 filterAddressing; uint8 filterMode;
uint8 addressU;
uint8 addressV;
}; };
void registerNativeRaster(void); void registerNativeRaster(void);

View File

@ -33,6 +33,7 @@ Image::create(int32 width, int32 height, int32 depth)
img->width = width; img->width = width;
img->height = height; img->height = height;
img->depth = depth; img->depth = depth;
img->bpp = depth < 8 ? 1 : depth/8;
img->stride = 0; img->stride = 0;
img->pixels = nil; img->pixels = nil;
img->palette = nil; img->palette = nil;
@ -50,7 +51,7 @@ void
Image::allocate(void) Image::allocate(void)
{ {
if(this->pixels == nil){ if(this->pixels == nil){
this->stride = this->width*(this->depth==4 ? 1 : this->depth/8); this->stride = this->width*this->bpp;
this->pixels = rwNewT(uint8, this->stride*this->height, MEMDUR_EVENT | ID_IMAGE); this->pixels = rwNewT(uint8, this->stride*this->height, MEMDUR_EVENT | ID_IMAGE);
this->flags |= 1; this->flags |= 1;
} }

View File

@ -12,6 +12,31 @@
namespace rw { namespace rw {
void
BBox::initialize(V3d *point)
{
this->inf = *point;
this->sup = *point;
}
void
BBox::addPoint(V3d *point)
{
if(point->x < this->inf.x)
this->inf.x = point->x;
if(point->y < this->inf.y)
this->inf.y = point->y;
if(point->z < this->inf.z)
this->inf.z = point->z;
if(point->x > this->sup.x)
this->sup.x = point->x;
if(point->y > this->sup.y)
this->sup.y = point->y;
if(point->z > this->sup.z)
this->sup.z = point->z;
}
void void
BBox::calculate(V3d *points, int32 n) BBox::calculate(V3d *points, int32 n)
{ {
@ -34,4 +59,12 @@ BBox::calculate(V3d *points, int32 n)
} }
} }
bool
BBox::containsPoint(V3d *point)
{
return point->x >= this->inf.x && point->x <= this->sup.x &&
point->y >= this->inf.y && point->y <= this->sup.y &&
point->z >= this->inf.z && point->z <= this->sup.z;
}
} }

View File

@ -7,9 +7,15 @@
namespace rw { namespace rw {
void SetRenderState(int32 state, uint32 value){ void SetRenderState(int32 state, uint32 value){
engine->device.setRenderState(state, (void*)(uintptr)value); }
void SetRenderStatePtr(int32 state, void *value){
engine->device.setRenderState(state, value); } engine->device.setRenderState(state, value); }
uint32 GetRenderState(int32 state){ uint32 GetRenderState(int32 state){
return (uint32)(uintptr)engine->device.getRenderState(state); }
void *GetRenderStatePtr(int32 state){
return engine->device.getRenderState(state); } return engine->device.getRenderState(state); }
// Im2D // Im2D
@ -17,7 +23,7 @@ uint32 GetRenderState(int32 state){
namespace im2d { namespace im2d {
float32 GetNearZ(void) { return engine->device.zNear; } float32 GetNearZ(void) { return engine->device.zNear; }
float32 GetFarZ(void) { return engine->device.zNear; } float32 GetFarZ(void) { return engine->device.zFar; }
void void
RenderIndexedPrimitive(PrimitiveType type, void *verts, int32 numVerts, void *indices, int32 numIndices) RenderIndexedPrimitive(PrimitiveType type, void *verts, int32 numVerts, void *indices, int32 numIndices)
{ {

View File

@ -384,7 +384,10 @@ struct BBox
V3d sup; V3d sup;
V3d inf; V3d inf;
void initialize(V3d *point);
void addPoint(V3d *point);
void calculate(V3d *points, int32 n); void calculate(V3d *points, int32 n);
bool containsPoint(V3d *point);
}; };
enum PrimitiveType enum PrimitiveType

View File

@ -29,12 +29,12 @@ class ObjPipeline;
struct Device struct Device
{ {
float32 zNear, zFar; float32 zNear, zFar;
void (*beginUpdate)(Camera*); void (*beginUpdate)(Camera*);
void (*endUpdate)(Camera*); void (*endUpdate)(Camera*);
void (*clearCamera)(Camera*, RGBA *col, uint32 mode); void (*clearCamera)(Camera*, RGBA *col, uint32 mode);
void (*showRaster)(Raster *raster); void (*showRaster)(Raster *raster);
void (*setRenderState)(int32 state, uint32 value); void (*setRenderState)(int32 state, void *value);
uint32 (*getRenderState)(int32 state); void *(*getRenderState)(int32 state);
// TODO: render line // TODO: render line
// TODO: render triangle // TODO: render triangle
@ -110,7 +110,6 @@ struct Engine
}; };
void *currentCamera; void *currentCamera;
void *currentWorld; void *currentWorld;
Texture *imtexture;
LinkList frameDirtyList; LinkList frameDirtyList;
// Dynamically allocated because of plugins // Dynamically allocated because of plugins
@ -154,8 +153,8 @@ namespace null {
void clearCamera(Camera*, RGBA *col, uint32 mode); void clearCamera(Camera*, RGBA *col, uint32 mode);
void showRaster(Raster*); void showRaster(Raster*);
void setRenderState(int32 state, uint32 value); void setRenderState(int32 state, void *value);
uint32 getRenderState(int32 state); void *getRenderState(int32 state);
void rasterCreate(Raster*); void rasterCreate(Raster*);
uint8 *rasterLock(Raster*, int32 level); uint8 *rasterLock(Raster*, int32 level);

View File

@ -125,6 +125,7 @@ struct Image
int32 flags; int32 flags;
int32 width, height; int32 width, height;
int32 depth; int32 depth;
int32 bpp; // bytes per pixel
int32 stride; int32 stride;
uint8 *pixels; uint8 *pixels;
uint8 *palette; uint8 *palette;

View File

@ -4,7 +4,12 @@ namespace rw {
enum RenderState enum RenderState
{ {
VERTEXALPHA = 0, TEXTURERASTER,
TEXTUREADDRESS,
TEXTUREADDRESSU,
TEXTUREADDRESSV,
TEXTUREFILTER,
VERTEXALPHA,
SRCBLEND, SRCBLEND,
DESTBLEND, DESTBLEND,
ZTESTENABLE, ZTESTENABLE,
@ -53,7 +58,9 @@ enum BlendFunction
}; };
void SetRenderState(int32 state, uint32 value); void SetRenderState(int32 state, uint32 value);
void SetRenderStatePtr(int32 state, void *value);
uint32 GetRenderState(int32 state); uint32 GetRenderState(int32 state);
void *GetRenderStatePtr(int32 state);
// Im2D // Im2D

View File

@ -262,6 +262,8 @@ defaultFindCB(const char *name)
return nil; return nil;
} }
// TODO: actually read the mask!
static Texture* static Texture*
defaultReadCB(const char *name, const char *mask) defaultReadCB(const char *name, const char *mask)
{ {

View File

@ -96,7 +96,11 @@ printScreen(const char *s, float32 x, float32 y)
s++; s++;
} }
engine->imtexture = curfont->tex;
rw::SetRenderStatePtr(rw::TEXTURERASTER, curfont->tex->raster);
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST,
vertices, curVert, indices, curIndex); vertices, curVert, indices, curIndex);

View File

@ -263,7 +263,9 @@ im2dtest(void)
verts[i].setV(vs[i].v, recipZ); verts[i].setV(vs[i].v, recipZ);
} }
rw::engine->imtexture = tex2; rw::SetRenderStatePtr(rw::TEXTURERASTER, tex2->raster);
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
rw::SetRenderState(rw::VERTEXALPHA, 1); rw::SetRenderState(rw::VERTEXALPHA, 1);
rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRISTRIP, rw::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRISTRIP,
&verts, 4, &indices, 4); &verts, 4, &indices, 4);
@ -305,7 +307,9 @@ im3dtest(void)
verts[i].setV(vs[i].v); verts[i].setV(vs[i].v);
} }
rw::engine->imtexture = tex; rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
rw::SetRenderState(rw::TEXTUREADDRESS, rw::Texture::WRAP);
rw::SetRenderState(rw::TEXTUREFILTER, rw::Texture::NEAREST);
/* /*
genIm3DTransform(verts, 8, nil); genIm3DTransform(verts, 8, nil);
@ -325,9 +329,9 @@ Draw(float timeDelta)
camera->update(); camera->update();
camera->m_rwcam->beginUpdate(); camera->m_rwcam->beginUpdate();
// Scene.clump->render(); Scene.clump->render();
// im2dtest(); // im2dtest();
tlTest(Scene.clump); // tlTest(Scene.clump);
// im3dtest(); // im3dtest();
// printScreen("Hello, World!", 10, 10); // printScreen("Hello, World!", 10, 10);

View File

@ -116,7 +116,15 @@ drawAtomic(Atomic *a)
im2dverts[idx].setColor(col.red, col.green, col.blue, col.alpha); im2dverts[idx].setColor(col.red, col.green, col.blue, col.alpha);
} }
engine->imtexture = m[i].material->texture; rw::Texture *tex = m[i].material->texture;
if(tex && tex->raster){
rw::SetRenderStatePtr(rw::TEXTURERASTER, tex->raster);
rw::SetRenderState(rw::TEXTUREADDRESSU, tex->getAddressU());
rw::SetRenderState(rw::TEXTUREADDRESSV, tex->getAddressV());
rw::SetRenderState(rw::TEXTUREFILTER, tex->getFilter());
}else
rw::SetRenderStatePtr(rw::TEXTURERASTER, nil);
im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST, im2d::RenderIndexedPrimitive(rw::PRIMTYPETRILIST,
im2dverts, g->numVertices, m[i].indices, m[i].numIndices); im2dverts, g->numVertices, m[i].indices, m[i].numIndices);
} }