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)
pcmd->UserCallback(cmd_list, pcmd);
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,
g_vertbuf+vtx_offset, cmd_list->VtxBuffer.Size,
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;
out = raster->lock(0);
if(pallength)

View File

@ -38,21 +38,32 @@ static VidmemRaster *vidmemRasters;
void addVidmemRaster(Raster *raster);
void removeVidmemRaster(Raster *raster);
// cached RW render states
static bool32 vertexAlpha;
static bool32 textureAlpha;
static uint32 srcblend, destblend;
static uint32 zwrite;
static uint32 ztest;
static uint32 fogenable;
static RGBA fogcolor;
static uint32 cullmode;
static uint32 alphafunc;
static uint32 alpharef;
struct RwRasterStateCache {
Raster *raster;
Texture::Addressing addressingU;
Texture::Addressing addressingV;
Texture::FilterMode filter;
};
#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 MAXNUMSTAGES 8
#define MAXNUMTEXSTATES (D3DTSS_CONSTANT+1)
#define MAXNUMSAMPLERSTATES (D3DSAMP_DMAPOFFSET+1)
@ -77,15 +88,50 @@ static uint32 d3dTextureStageStates[MAXNUMTEXSTATES][MAXNUMSTAGES];
static uint32 d3dSamplerStates[MAXNUMSAMPLERSTATES][MAXNUMSTAGES];
// TODO: not only rasters, make a struct
static Raster *d3dRaster[MAXNUMSTAGES];
static bool validStates[MAXNUMSTATES];
static bool validTexStates[MAXNUMTEXSTATES];
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
void
@ -176,8 +222,16 @@ resetD3d9Device(void)
int32 i;
uint32 s, t;
for(i = 0; i < MAXNUMSTAGES; i++){
d3dRaster[i] = nil;
d3ddevice->SetTexture(i, nil);
Raster *raster = rwStateCache.texstage[i].raster;
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++)
if(validStates[s])
@ -197,146 +251,25 @@ resetD3d9Device(void)
static void
setVertexAlpha(bool32 enable)
{
if(vertexAlpha != enable){
if(!textureAlpha){
if(rwStateCache.vertexAlpha != enable){
if(!rwStateCache.textureAlpha){
setRenderState(D3DRS_ALPHABLENDENABLE, 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
setRasterStage(uint32 stage, Raster *raster)
{
bool32 alpha;
D3dRaster *d3draster = nil;
if(raster != d3dRaster[stage]){
d3dRaster[stage] = raster;
if(raster != rwStateCache.texstage[stage].raster){
rwStateCache.texstage[stage].raster = raster;
if(raster){
assert(raster->platform == PLATFORM_D3D8 ||
raster->platform == PLATFORM_D3D9);
d3draster = PLUGINOFFSET(D3dRaster, raster, nativeRasterOffset);
d3ddevice->SetTexture(stage, (IDirect3DTexture9*)d3draster->texture);
alpha = d3draster->hasAlpha;
@ -345,9 +278,9 @@ setRasterStage(uint32 stage, Raster *raster)
alpha = 0;
}
if(stage == 0){
if(textureAlpha != alpha){
textureAlpha = alpha;
if(!vertexAlpha){
if(rwStateCache.textureAlpha != alpha){
rwStateCache.textureAlpha = alpha;
if(!rwStateCache.vertexAlpha){
setRenderState(D3DRS_ALPHABLENDENABLE, 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
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){
setRasterStage(stage, nil);
return;
}
if(tex->raster){
setSamplerState(stage, D3DSAMP_MAGFILTER, filternomip[tex->getFilter()]);
setSamplerState(stage, D3DSAMP_MINFILTER, filternomip[tex->getFilter()]);
setSamplerState(stage, D3DSAMP_ADDRESSU, wrap[tex->getAddressU()]);
setSamplerState(stage, D3DSAMP_ADDRESSV, wrap[tex->getAddressV()]);
setFilterMode(stage, tex->getFilter());
setAddressU(stage, tex->getAddressU());
setAddressV(stage, tex->getAddressV());
}
setRasterStage(stage, tex->raster);
}
@ -428,6 +379,152 @@ setMaterial(SurfaceProperties surfProps, rw::RGBA color)
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
void
@ -750,26 +847,26 @@ initD3D(void)
// TODO: do some real stuff here
d3ddevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
alphafunc = ALPHAGREATEREQUAL;
rwStateCache.alphafunc = ALPHAGREATEREQUAL;
d3ddevice->SetRenderState(D3DRS_ALPHAREF, 10);
alpharef = 10;
rwStateCache.alpharef = 10;
d3ddevice->SetRenderState(D3DRS_FOGENABLE, FALSE);
fogenable = 0;
rwStateCache.fogenable = 0;
d3ddevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
// TODO: more fog stuff
d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
cullmode = CULLNONE;
rwStateCache.cullmode = CULLNONE;
d3ddevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD);
d3ddevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
srcblend = BLENDSRCALPHA;
rwStateCache.srcblend = BLENDSRCALPHA;
d3ddevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
destblend = BLENDINVSRCALPHA;
rwStateCache.destblend = BLENDINVSRCALPHA;
d3ddevice->SetRenderState(D3DRS_ALPHABLENDENABLE, 0);
vertexAlpha = 0;
textureAlpha = 0;
rwStateCache.vertexAlpha = 0;
rwStateCache.textureAlpha = 0;
setTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
// setTextureStageState(0, D3DTSS_CONSTANT, 0xFFFFFFFF);

View File

@ -76,7 +76,6 @@ im2DRenderIndexedPrimitive(PrimitiveType primType,
d3ddevice->SetStreamSource(0, im2dvertbuf, 0, sizeof(Im2DVertex));
d3ddevice->SetIndices(im2dindbuf);
d3ddevice->SetVertexDeclaration(im2ddecl);
d3d::setTexture(0, engine->imtexture);
setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
setTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT);
@ -175,7 +174,6 @@ im3DRenderIndexed(PrimitiveType primType, void *indices, int32 numIndices)
unlockIndices(im3dindbuf);
d3ddevice->SetIndices(im3dindbuf);
d3d::setTexture(0, engine->imtexture);
setTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
setTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
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->currentCamera = nil;
engine->currentWorld = nil;
engine->imtexture = nil;
// Initialize device
// Device and possibly OS specific!
@ -207,8 +206,8 @@ void endUpdate(Camera*) { }
void clearCamera(Camera*,RGBA*,uint32) { }
void showRaster(Raster*) { }
void setRenderState(int32, uint32) { }
uint32 getRenderState(int32) { return 0; }
void setRenderState(int32, void*) { }
void *getRenderState(int32) { return 0; }
void im2DRenderIndexedPrimitive(PrimitiveType, void*, int32, void*, int32) { }

View File

@ -1,6 +1,7 @@
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include "../rwbase.h"
#include "../rwerror.h"
@ -83,15 +84,28 @@ static bool32 stateDirty = 1;
static bool32 sceneDirty = 1;
static bool32 objectDirty = 1;
// cached render states
static bool32 vertexAlpha;
static uint32 alphaTestEnable;
static uint32 alphaFunc;
static bool32 textureAlpha;
static uint32 srcblend, destblend;
static uint32 zwrite;
static uint32 ztest;
static uint32 cullmode;
struct RwRasterStateCache {
Raster *raster;
Texture::Addressing addressingU;
Texture::Addressing addressingV;
Texture::FilterMode filter;
};
#define MAXNUMSTAGES 8
// 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;
@ -113,9 +127,9 @@ static void
setAlphaTest(bool32 enable)
{
uint32 shaderfunc;
if(alphaTestEnable != enable){
alphaTestEnable = enable;
shaderfunc = alphaTestEnable ? alphaFunc : ALPHAALWAYS;
if(rwStateCache.alphaTestEnable != enable){
rwStateCache.alphaTestEnable = enable;
shaderfunc = rwStateCache.alphaTestEnable ? rwStateCache.alphaFunc : ALPHAALWAYS;
if(uniformState.alphaFunc != shaderfunc){
uniformState.alphaFunc = shaderfunc;
stateDirty = 1;
@ -127,9 +141,9 @@ static void
setAlphaTestFunction(uint32 function)
{
uint32 shaderfunc;
if(alphaFunc != function){
alphaFunc = function;
shaderfunc = alphaTestEnable ? alphaFunc : ALPHAALWAYS;
if(rwStateCache.alphaFunc != function){
rwStateCache.alphaFunc = function;
shaderfunc = rwStateCache.alphaTestEnable ? rwStateCache.alphaFunc : ALPHAALWAYS;
if(uniformState.alphaFunc != shaderfunc){
uniformState.alphaFunc = shaderfunc;
stateDirty = 1;
@ -140,47 +154,201 @@ setAlphaTestFunction(uint32 function)
static void
setVertexAlpha(bool32 enable)
{
if(vertexAlpha != enable){
if(!textureAlpha){
if(rwStateCache.vertexAlpha != enable){
if(!rwStateCache.textureAlpha){
(enable ? glEnable : glDisable)(GL_BLEND);
setAlphaTest(enable);
}
vertexAlpha = enable;
rwStateCache.vertexAlpha = enable;
}
}
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){
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(value);
break;
case SRCBLEND:
if(srcblend != value){
srcblend = value;
glBlendFunc(blendMap[srcblend], blendMap[destblend]);
if(rwStateCache.srcblend != value){
rwStateCache.srcblend = value;
glBlendFunc(blendMap[rwStateCache.srcblend], blendMap[rwStateCache.destblend]);
}
break;
case DESTBLEND:
if(destblend != value){
destblend = value;
glBlendFunc(blendMap[srcblend], blendMap[destblend]);
if(rwStateCache.destblend != value){
rwStateCache.destblend = value;
glBlendFunc(blendMap[rwStateCache.srcblend], blendMap[rwStateCache.destblend]);
}
break;
case ZTESTENABLE:
if(ztest != value){
ztest = value;
if(ztest)
if(rwStateCache.ztest != value){
rwStateCache.ztest = value;
if(rwStateCache.ztest)
glEnable(GL_DEPTH_TEST);
else
glDisable(GL_DEPTH_TEST);
}
break;
case ZWRITEENABLE:
if(zwrite != (value ? GL_TRUE : GL_FALSE)){
zwrite = value ? GL_TRUE : GL_FALSE;
glDepthMask(zwrite);
if(rwStateCache.zwrite != (value ? GL_TRUE : GL_FALSE)){
rwStateCache.zwrite = value ? GL_TRUE : GL_FALSE;
glDepthMask(rwStateCache.zwrite);
}
break;
case FOGENABLE:
@ -200,13 +368,13 @@ setRenderState(int32 state, uint32 value)
stateDirty = 1;
break;
case CULLMODE:
if(cullmode != value){
cullmode = value;
if(cullmode == CULLNONE)
if(rwStateCache.cullmode != value){
rwStateCache.cullmode = value;
if(rwStateCache.cullmode == CULLNONE)
glDisable(GL_CULL_FACE);
else{
glEnable(GL_CULL_FACE);
glCullFace(cullmode == CULLBACK ? GL_BACK : GL_FRONT);
glCullFace(rwStateCache.cullmode == CULLBACK ? GL_BACK : GL_FRONT);
}
}
break;
@ -223,41 +391,72 @@ setRenderState(int32 state, uint32 value)
}
}
static uint32
static void*
getRenderState(int32 state)
{
uint32 val;
RGBA rgba;
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:
return vertexAlpha;
val = rwStateCache.vertexAlpha;
break;
case SRCBLEND:
return srcblend;
val = rwStateCache.srcblend;
break;
case DESTBLEND:
return destblend;
val = rwStateCache.destblend;
break;
case ZTESTENABLE:
return ztest;
val = rwStateCache.ztest;
break;
case ZWRITEENABLE:
return zwrite;
val = rwStateCache.zwrite;
break;
case FOGENABLE:
return uniformState.fogEnable;
val = uniformState.fogEnable;
break;
case 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:
return cullmode;
val = rwStateCache.cullmode;
break;
case ALPHATESTFUNC:
return alphaFunc;
val = rwStateCache.alphaFunc;
break;
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
resetRenderState(void)
{
alphaFunc = ALPHAGREATEREQUAL;
{
rwStateCache.alphaFunc = ALPHAGREATEREQUAL;
uniformState.alphaFunc = 0;
uniformState.alphaRef = 10.0f/255.0f;
uniformState.fogEnable = 0;
@ -265,28 +464,28 @@ resetRenderState(void)
uniformState.fogColor = { 1.0f, 1.0f, 1.0f, 1.0f };
stateDirty = 1;
vertexAlpha = 0;
textureAlpha = 0;
rwStateCache.vertexAlpha = 0;
rwStateCache.textureAlpha = 0;
glDisable(GL_BLEND);
alphaTestEnable = 0;
rwStateCache.alphaTestEnable = 0;
srcblend = BLENDSRCALPHA;
destblend = BLENDINVSRCALPHA;
glBlendFunc(blendMap[srcblend], blendMap[destblend]);
rwStateCache.srcblend = BLENDSRCALPHA;
rwStateCache.destblend = BLENDINVSRCALPHA;
glBlendFunc(blendMap[rwStateCache.srcblend], blendMap[rwStateCache.destblend]);
zwrite = GL_TRUE;
glDepthMask(zwrite);
rwStateCache.zwrite = GL_TRUE;
glDepthMask(rwStateCache.zwrite);
ztest = 1;
rwStateCache.ztest = 1;
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
cullmode = CULLNONE;
rwStateCache.cullmode = CULLNONE;
glDisable(GL_CULL_FACE);
for(int i = 0; i < 8; i++){
for(int i = 0; i < MAXNUMSTAGES; i++){
glActiveTexture(GL_TEXTURE0+i);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_2D, whitetex);
}
}
@ -347,61 +546,6 @@ setViewMatrix(float32 *mat)
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
flushCache(void)
{
@ -593,6 +737,14 @@ initOpenGL(void)
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();
glGenVertexArrays(1, &vao);
@ -619,14 +771,6 @@ initOpenGL(void)
GL_DYNAMIC_DRAW);
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_fs_gl3.inc"
simpleShader = Shader::fromStrings(simple_vert_src, simple_frag_src);

View File

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

View File

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

View File

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

View File

@ -33,6 +33,7 @@ Image::create(int32 width, int32 height, int32 depth)
img->width = width;
img->height = height;
img->depth = depth;
img->bpp = depth < 8 ? 1 : depth/8;
img->stride = 0;
img->pixels = nil;
img->palette = nil;
@ -50,7 +51,7 @@ void
Image::allocate(void)
{
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->flags |= 1;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -96,7 +96,11 @@ printScreen(const char *s, float32 x, float32 y)
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,
vertices, curVert, indices, curIndex);

View File

@ -263,7 +263,9 @@ im2dtest(void)
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::im2d::RenderIndexedPrimitive(rw::PRIMTYPETRISTRIP,
&verts, 4, &indices, 4);
@ -305,7 +307,9 @@ im3dtest(void)
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);
@ -325,9 +329,9 @@ Draw(float timeDelta)
camera->update();
camera->m_rwcam->beginUpdate();
// Scene.clump->render();
Scene.clump->render();
// im2dtest();
tlTest(Scene.clump);
// tlTest(Scene.clump);
// im3dtest();
// 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);
}
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,
im2dverts, g->numVertices, m[i].indices, m[i].numIndices);
}