1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-15 09:34:18 +02:00

#15 basic D3D9 renderer (WIP)

This commit is contained in:
XProger
2018-05-11 13:38:18 +03:00
parent 8f2b80c7a8
commit 6b94d7d0e0
23 changed files with 1292 additions and 383 deletions

View File

@@ -8,10 +8,6 @@
#define NO_CLIP_PLANE 1000000.0f
#define WATER_FOG_DIST (6 * 1024)
//#define WATER_USE_GRID
#define UNDERWATER_COLOR "#define UNDERWATER_COLOR vec3(0.6, 0.9, 0.9)\n"
struct ShaderCache {
enum Effect { FX_NONE = 0, FX_UNDERWATER = 1, FX_ALPHA_TEST = 2, FX_CLIP_PLANE = 4 };
@@ -97,7 +93,6 @@ struct ShaderCache {
compile(Core::passFilter, Shader::FILTER_DOWNSAMPLE, fx, RS_COLOR_WRITE);
compile(Core::passFilter, Shader::FILTER_GRAYSCALE, fx, RS_COLOR_WRITE);
compile(Core::passFilter, Shader::FILTER_BLUR, fx, RS_COLOR_WRITE);
compile(Core::passFilter, Shader::FILTER_MIXER, fx, RS_COLOR_WRITE);
}
void prepareGUI(int fx) {
@@ -114,92 +109,58 @@ struct ShaderCache {
fx |= FX_ALPHA_TEST;
#ifndef FFP
char def[1024], ext[255];
ext[0] = 0;
int def[SD_MAX], defCount = 0;
#define SD_ADD(x) (def[defCount++] = SD_##x)
if (Core::settings.detail.shadows) {
if (Core::support.shadowSampler) {
#ifdef _GAPI_GLES
strcat(ext, "#extension GL_EXT_shadow_samplers : require\n");
#endif
strcat(ext, "#define SHADOW_SAMPLER\n");
SD_ADD(SHADOW_SAMPLER);
} else {
if (Core::support.depthTexture)
strcat(ext, "#define SHADOW_DEPTH\n");
SD_ADD(SHADOW_DEPTH);
else
strcat(ext, "#define SHADOW_COLOR\n");
SD_ADD(SHADOW_COLOR);
}
}
const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT", "WATER", "FILTER", "GUI" };
const char *src = NULL;
const char *typ = NULL;
switch (pass) {
case Core::passCompose :
case Core::passShadow :
case Core::passAmbient : {
static const char *typeNames[] = { "SPRITE", "FLASH", "ROOM", "ENTITY", "MIRROR" };
def[defCount++] = SD_TYPE_SPRITE + type;
src = GAPI::SHADER_BASE;
typ = typeNames[type];
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_CONTACTS %d\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, passNames[pass], typ, MAX_LIGHTS, MAX_CONTACTS, WATER_FOG_DIST);
#ifdef MERGE_SPRITES
if (type == Shader::SPRITE)
strcat(def, "#define ALIGN_SPRITES 1\n");
#endif
if (fx & FX_UNDERWATER) SD_ADD(UNDERWATER);
if (fx & FX_ALPHA_TEST) SD_ADD(ALPHA_TEST);
if (fx & FX_UNDERWATER) strcat(def, "#define UNDERWATER\n" UNDERWATER_COLOR);
if (fx & FX_ALPHA_TEST) strcat(def, "#define ALPHA_TEST\n");
if (pass == Core::passCompose) {
if (fx & FX_CLIP_PLANE)
strcat(def, "#define CLIP_PLANE\n");
if (Core::settings.detail.lighting > Core::Settings::LOW && (type == Shader::ENTITY || type == Shader::ROOM))
strcat(def, "#define OPT_LIGHTING\n");
SD_ADD(CLIP_PLANE);
if (Core::settings.detail.lighting > Core::Settings::MEDIUM && (type == Shader::ENTITY))
strcat(def, "#define OPT_AMBIENT\n");
SD_ADD(OPT_AMBIENT);
if (Core::settings.detail.shadows > Core::Settings::LOW && (type == Shader::ENTITY || type == Shader::ROOM)) {
strcat(def, "#define OPT_SHADOW\n");
SD_ADD(OPT_SHADOW);
if (Core::settings.detail.shadows > Core::Settings::MEDIUM) {
strcat(def, "#define OPT_SHADOW_HIGH\n");
sprintf(def, "%s#define SHADOW_TEXEL vec3(1.0 / %d.0, 1.0 / %d.0, 0.0)\n#define SHADOW_OBJ_MAX %d\n", def, SHADOW_TEX_WIDTH, SHADOW_TEX_HEIGHT, SHADOW_OBJ_MAX);
} else
sprintf(def, "%s#define SHADOW_TEXEL vec3(1.0 / %d.0, 1.0 / %d.0, 0.0)\n#define SHADOW_OBJ_MAX %d\n", def, SHADOW_TEX_BIG_WIDTH, SHADOW_TEX_BIG_HEIGHT, 1);
if (Core::settings.detail.shadows > Core::Settings::MEDIUM)
SD_ADD(OPT_SHADOW_HIGH);
}
if (Core::settings.detail.shadows > Core::Settings::MEDIUM && (type == Shader::ROOM))
strcat(def, "#define OPT_CONTACT\n");
SD_ADD(OPT_CONTACT);
if (Core::settings.detail.water > Core::Settings::MEDIUM && (type == Shader::ENTITY || type == Shader::ROOM) && (fx & FX_UNDERWATER))
strcat(def, "#define OPT_CAUSTICS\n");
SD_ADD(OPT_CAUSTICS);
}
break;
}
case Core::passWater : {
static const char *typeNames[] = { "DROP", "STEP", "CAUSTICS", "MASK", "COMPOSE" };
src = GAPI::SHADER_WATER;
typ = typeNames[type];
sprintf(def, "%s#define PASS_%s\n#define WATER_%s\n#define WATER_FOG_DIST (1.0/%d.0)\n" UNDERWATER_COLOR, ext, passNames[pass], typ, WATER_FOG_DIST);
#ifdef WATER_USE_GRID
strcat(def, "#define WATER_USE_GRID\n");
#endif
break;
}
case Core::passFilter : {
static const char *typeNames[] = { "DEFAULT", "DOWNSAMPLE", "GRAYSCALE", "BLUR", "MIXER", "EQUIRECTANGULAR" };
src = GAPI::SHADER_FILTER;
typ = typeNames[type];
sprintf(def, "%s#define PASS_%s\n#define FILTER_%s\n", ext, passNames[pass], typ);
break;
}
case Core::passGUI : {
static const char *typeNames[] = { "DEFAULT" };
src = GAPI::SHADER_GUI;
typ = typeNames[type];
sprintf(def, "%s#define PASS_%s\n", ext, passNames[pass]);
break;
}
case Core::passWater : def[defCount++] = SD_WATER_DROP + type; break;
case Core::passFilter : def[defCount++] = SD_FILTER_DEFAULT + type; break;
case Core::passGUI : break;
default : ASSERT(false);
}
LOG("shader: compile %s -> %s %s%s%s\n", passNames[pass], typ, (fx & FX_UNDERWATER) ? "underwater " : "", (fx & FX_ALPHA_TEST) ? "alphaTest " : "", (fx & FX_CLIP_PLANE) ? "clipPlane" : "");
return shaders[pass][type][fx] = new Shader(src, def);
#undef SD_ADD
LOG("shader: %s(%d) %s%s%s\n", Core::passNames[pass], type, (fx & FX_UNDERWATER) ? "u" : "", (fx & FX_ALPHA_TEST) ? "a" : "", (fx & FX_CLIP_PLANE) ? "c" : "");
return shaders[pass][type][fx] = new Shader(pass, def, defCount);
#else
return NULL;
#endif
@@ -220,7 +181,7 @@ struct ShaderCache {
Shader *shader = getShader(pass, type, fx);
if (shader)
shader->bind();
shader->setup();
Core::setAlphaTest((fx & FX_ALPHA_TEST) != 0);
}
@@ -477,11 +438,11 @@ struct WaterCache {
int *mf = new int[4 * w * 64 * h * 64];
memset(mf, 0, sizeof(int) * 4 * w * 64 * h * 64);
data[0] = new Texture(w * 64, h * 64, FMT_RGBA_HALF, 0, mf);
data[1] = new Texture(w * 64, h * 64, FMT_RGBA_HALF);
data[0] = new Texture(w * 64, h * 64, FMT_RGBA_HALF, OPT_TARGET, mf);
data[1] = new Texture(w * 64, h * 64, FMT_RGBA_HALF, OPT_TARGET);
delete[] mf;
caustics = Core::settings.detail.water > Core::Settings::MEDIUM ? new Texture(512, 512, FMT_RGBA) : NULL;
caustics = Core::settings.detail.water > Core::Settings::MEDIUM ? new Texture(512, 512, FMT_RGBA, OPT_TARGET) : NULL;
#ifdef BLUR_CAUSTICS
caustics_tmp = Core::settings.detail.water > Core::Settings::MEDIUM ? new Texture(512, 512, Texture::RGBA) : NULL;
#endif
@@ -513,7 +474,7 @@ struct WaterCache {
} drops[MAX_DROPS];
WaterCache(IGame *game) : game(game), level(game->getLevel()), refract(NULL), count(0), dropCount(0) {
reflect = new Texture(512, 512, FMT_RGBA);
reflect = new Texture(512, 512, FMT_RGBA, OPT_TARGET);
}
~WaterCache() {
@@ -628,7 +589,7 @@ struct WaterCache {
game->setShader(Core::passWater, Shader::WATER_DROP);
Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, 1.0f, 1.0f));
vec3 rPosScale[2] = { vec3(0.0f), vec3(1.0f) };
vec4 rPosScale[2] = { vec4(0.0f), vec4(1.0f) };
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
for (int i = 0; i < dropCount; i++) {
@@ -666,7 +627,7 @@ struct WaterCache {
// calc caustics
game->setShader(Core::passWater, Shader::WATER_CAUSTICS);
vec3 rPosScale[2] = { vec3(0.0f), vec3(32767.0f / PLANE_DETAIL) };
vec4 rPosScale[2] = { vec4(0.0f), vec4(32767.0f / PLANE_DETAIL) };
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
float sx = item.size.x * DETAIL / (item.data[0]->width / 2);
@@ -713,7 +674,8 @@ struct WaterCache {
Item &item = items[i];
if (!item.visible) continue;
Core::active.shader->setParam(uPosScale, item.pos, 2);
vec4 rPosScale[2] = { vec4(item.pos, 0.0f), vec4(item.size, 1.0) };
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
game->getMesh()->renderQuad();
}
@@ -870,11 +832,12 @@ struct WaterCache {
Core::setCullMode(cmNone);
Core::setBlendMode(bmAlpha);
#ifdef WATER_USE_GRID
vec3 rPosScale[2] = { item.pos, item.size * vec3(1.0f / PLANE_DETAIL, 512.0f, 1.0f / PLANE_DETAIL) };
vec4 rPosScale[2] = { vec4(item.pos, 0.0f), vec4(item.size * vec3(1.0f / PLANE_DETAIL, 512.0f, 1.0f / PLANE_DETAIL), 1.0f) };
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
game->getMesh()->renderPlane();
#else
Core::active.shader->setParam(uPosScale, item.pos, 2);
vec4 rPosScale[2] = { vec4(item.pos, 0.0f), vec4(item.size, 1.0) };
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
game->getMesh()->renderQuad();
#endif
Core::setCullMode(cmFront);

View File

@@ -514,9 +514,9 @@ struct Camera : ICamera {
// update room for eye (with HMD offset)
if (Core::settings.detail.stereo == Core::Settings::STEREO_VR)
level->getSector(eye.room, Core::viewPos);
level->getSector(eye.room, Core::viewPos.xyz());
frustum->pos = Core::viewPos;
frustum->pos = Core::viewPos.xyz();
frustum->calcPlanes(Core::mViewProj);
}

View File

@@ -117,7 +117,7 @@ struct Controller {
Basis *joints;
int jointsFrame;
vec3 ambient[6];
vec4 ambient[6];
float specular;
float intensity;
@@ -159,7 +159,7 @@ struct Controller {
specular = 0.0f;
intensity = e.intensity == -1 ? -1.0f : intensityf(e.intensity);
timer = 0.0f;
ambient[0] = ambient[1] = ambient[2] = ambient[3] = ambient[4] = ambient[5] = vec3(intensityf(getRoom().ambient));
ambient[0] = ambient[1] = ambient[2] = ambient[3] = ambient[4] = ambient[5] = vec4(intensityf(getRoom().ambient));
targetLight = NULL;
updateLights(false);
visibleMask = 0xFFFFFFFF;
@@ -1255,7 +1255,6 @@ struct Controller {
float alpha = lerp(0.7f, 0.90f, clamp((info.floor - boxA.max.y) / 1024.0f, 0.0f, 1.0f) );
float lum = 0.5f * (1.0f - alpha);
Core::setMaterial(lum, lum, lum, alpha);
Core::active.shader->setParam(uAmbient, vec3(0.0f));
Core::setDepthWrite(false);
mesh->renderShadowBlob();

View File

@@ -11,9 +11,10 @@
#define OS_PTHREAD_MT
#ifdef WIN32
#define _OS_WIN 1
#define _GAPI_GL 1
//#define _GAPI_VULKAN
#define _OS_WIN 1
//#define _GAPI_GL 1
#define _GAPI_D3D9 1
//#define _GAPI_VULKAN 1
#include <windows.h>
@@ -83,6 +84,7 @@
#include "utils.h"
// muse be equal with base shader
#define SHADOW_OBJ_COLS 4
#define SHADOW_OBJ_ROWS 2
#define SHADOW_TEX_TILE 128
@@ -353,7 +355,8 @@ enum TexOption {
OPT_CUBEMAP = 1,
OPT_MIPMAPS = 2,
OPT_NEAREST = 4,
OPT_PROXY = 8,
OPT_TARGET = 8,
OPT_PROXY = 16,
};
// Pipeline State Object
@@ -415,15 +418,50 @@ struct MeshRange {
E( uViewPos ) \
E( uLightPos ) \
E( uLightColor ) \
E( uAnimTexRanges ) \
E( uAnimTexOffsets ) \
E( uRoomSize ) \
E( uPosScale ) \
E( uContacts )
enum AttribType { SHADER_ATTRIBS(DECL_ENUM) aMAX };
enum SamplerType { SHADER_SAMPLERS(DECL_ENUM) sMAX };
enum UniformType { SHADER_UNIFORMS(DECL_ENUM) uMAX };
#define SHADER_DEFINES(E) \
/* shadow types */ \
E( SHADOW_SAMPLER ) \
E( SHADOW_DEPTH ) \
E( SHADOW_COLOR ) \
/* compose types */ \
E( TYPE_SPRITE ) \
E( TYPE_FLASH ) \
E( TYPE_ROOM ) \
E( TYPE_ENTITY ) \
E( TYPE_MIRROR ) \
/* water sub-passes */ \
E( WATER_DROP ) \
E( WATER_STEP ) \
E( WATER_CAUSTICS ) \
E( WATER_MASK ) \
E( WATER_COMPOSE ) \
/* filter types */ \
E( FILTER_DEFAULT ) \
E( FILTER_DOWNSAMPLE ) \
E( FILTER_GRAYSCALE ) \
E( FILTER_BLUR ) \
E( FILTER_EQUIRECTANGULAR ) \
/* options */ \
E( UNDERWATER ) \
E( ALPHA_TEST ) \
E( CLIP_PLANE ) \
E( OPT_AMBIENT ) \
E( OPT_SHADOW ) \
E( OPT_SHADOW_HIGH ) \
E( OPT_CONTACT ) \
E( OPT_CAUSTICS )
enum AttribType { SHADER_ATTRIBS(DECL_ENUM) aMAX };
enum SamplerType { SHADER_SAMPLERS(DECL_ENUM) sMAX };
enum UniformType { SHADER_UNIFORMS(DECL_ENUM) uMAX };
#define DECL_SD_ENUM(v) SD_##v,
enum ShaderDefine { SHADER_DEFINES(DECL_SD_ENUM) SD_MAX };
#undef DECL_SD_ENUM
const char *AttribName[aMAX] = { SHADER_ATTRIBS(DECL_STR) };
const char *SamplerName[sMAX] = { SHADER_SAMPLERS(DECL_STR) };
@@ -452,7 +490,7 @@ namespace Core {
mat4 mModel, mView, mProj, mViewProj, mViewInv;
mat4 mLightProj[SHADOW_OBJ_MAX];
Basis basis;
vec3 viewPos;
vec4 viewPos;
vec4 lightPos[MAX_LIGHTS];
vec4 lightColor[MAX_LIGHTS];
vec4 params;
@@ -463,17 +501,18 @@ namespace Core {
enum Pass { passCompose, passShadow, passAmbient, passWater, passFilter, passGUI, passMAX } pass;
const char *passNames[Core::passMAX] = { "COMPOSE", "SHADOW", "AMBIENT", "WATER", "FILTER", "GUI" };
Texture *defaultTarget;
int32 renderState;
struct Active {
const PSO *pso;
Shader *shader;
int32 renderState;
const PSO *pso;
GAPI::Shader *shader;
GAPI::Texture *textures[8];
GAPI::Texture *target;
int32 renderState;
uint32 targetFace;
uint32 targetOp;
Viewport viewport; // TODO: ivec4
@@ -483,9 +522,6 @@ namespace Core {
uint32 VAO;
uint32 iBuffer;
uint32 vBuffer;
#elif _GAPI_SCEGU
Index *iBuffer;
GAPI::Vertex *vBuffer;
#endif
int32 basisCount;
@@ -527,6 +563,8 @@ namespace Core {
#ifdef _GAPI_GL
#include "gapi_gl.h"
#elif _GAPI_D3D9
#include "gapi_d3d9.h"
#elif _GAPI_GX
#include "gapi_gx.h"
#elif _GAPI_SCEGU
@@ -890,9 +928,11 @@ namespace Core {
void beginFrame() {
Core::stats.start();
GAPI::beginFrame();
}
void endFrame() {
GAPI::endFrame();
Core::stats.stop();
}
@@ -904,13 +944,15 @@ namespace Core {
GAPI::setViewProj(mView, mProj);
}
void DIP(int iStart, int iCount, Index *iBuffer) {
void DIP(GAPI::Mesh *mesh, const MeshRange &range) {
mesh->bind(range);
stats.dips++;
stats.tris += iCount / 3;
stats.tris += range.iCount / 3;
validateRenderState();
GAPI::DIP(iStart, iCount, iBuffer);
GAPI::DIP(mesh, range);
}
PSO* psoCreate(Shader *shader, uint32 renderState, TexFormat colorFormat = FMT_RGBA, TexFormat depthFormat = FMT_DEPTH, const vec4 &clearColor = vec4(0.0f)) {
@@ -934,7 +976,7 @@ namespace Core {
ASSERT(pso);
ASSERT(pso->data);
ASSERT(pso->shader);
((Shader*)pso->shader)->bind();
((Shader*)pso->shader)->setup();
GAPI::bindPSO(pso);
Core::active.pso = pso;

View File

@@ -72,7 +72,7 @@ namespace Game {
}
void init(const char *lvlName = NULL) {
#ifdef _DEBUG
#ifdef DEBUG_RENDER
Debug::init();
#endif
char fileName[255];
@@ -87,7 +87,7 @@ namespace Game {
}
void deinit() {
#ifdef _DEBUG
#ifdef DEBUG_RENDER
Debug::deinit();
#endif
delete level;
@@ -183,7 +183,7 @@ namespace Game {
PROFILE_TIMING(Core::stats.tFrame);
level->render();
#ifdef _DEBUG
#ifdef DEBUG_RENDER
level->renderDebug();
#endif
}

533
src/gapi_d3d9.h Normal file
View File

@@ -0,0 +1,533 @@
#ifndef H_GAPI_D3D9
#define H_GAPI_D3D9
#include "core.h"
#include <d3d9.h>
#define PROFILE_MARKER(title)
#define PROFILE_LABEL(id, name, label)
#define PROFILE_TIMING(time)
extern LPDIRECT3D9 D3D;
extern LPDIRECT3DDEVICE9 device;
namespace GAPI {
#include "shaders/base_vs.h"
#include "shaders/base_ps.h"
#include "shaders/water_vs.h"
#include "shaders/water_ps.h"
#include "shaders/filter_vs.h"
#include "shaders/filter_ps.h"
#include "shaders/gui_vs.h"
#include "shaders/gui_ps.h"
const char *SHADER_BASE = NULL;
const char *SHADER_WATER = NULL;
const char *SHADER_FILTER = NULL;
const char *SHADER_GUI = NULL;
using namespace Core;
typedef ::Vertex Vertex;
int cullMode, blendMode;
uint32 clearColor;
LPDIRECT3DVERTEXDECLARATION9 vertexDecl;
// Shader
enum {
USAGE_VS,
USAGE_PS,
};
static const struct Binding {
int reg;
int usage;
} bindings[uMAX] = {
{ 0, USAGE_VS | USAGE_PS }, // uParam
{ 1, USAGE_VS | USAGE_PS }, // uTexParam
{ 2, USAGE_VS | USAGE_PS }, // uViewProj
{ 6, USAGE_VS | USAGE_PS }, // uBasis
{ 70, USAGE_VS | USAGE_PS }, // uLightProj
{ 102, USAGE_VS | USAGE_PS }, // uMaterial
{ 103, USAGE_VS | USAGE_PS }, // uAmbient
{ 109, USAGE_VS | USAGE_PS }, // uFogParams
{ 110, USAGE_VS | USAGE_PS }, // uViewPos
{ 111, USAGE_VS | USAGE_PS }, // uLightPos
{ 115, USAGE_VS | USAGE_PS }, // uLightColor
{ 119, USAGE_VS | USAGE_PS }, // uRoomSize
{ 120, USAGE_VS | USAGE_PS }, // uPosScale
{ 122, USAGE_VS | USAGE_PS }, // uContacts
};
struct Shader {
LPDIRECT3DVERTEXSHADER9 VS;
LPDIRECT3DPIXELSHADER9 PS;
Shader() : VS(NULL), PS(NULL) {}
void init(Core::Pass pass, int *def, int defCount) {
const BYTE *vSrc, *pSrc;
switch (pass) {
case Core::passCompose :
case Core::passShadow :
case Core::passAmbient : vSrc = BASE_VS; pSrc = BASE_PS; break;
case Core::passWater : vSrc = WATER_VS; pSrc = WATER_PS; break;
case Core::passFilter : vSrc = FILTER_VS; pSrc = FILTER_PS; break;
case Core::passGUI : vSrc = GUI_VS; pSrc = GUI_PS; break;
default : ASSERT(false); LOG("! wrong pass id\n"); return;
}
device->CreateVertexShader ((DWORD*)vSrc, &VS);
device->CreatePixelShader ((DWORD*)pSrc, &PS);
}
void deinit() {
if (VS) VS->Release();
if (PS) PS->Release();
}
void bind() {
if (Core::active.shader != this) {
Core::active.shader = this;
device->SetVertexShader(VS);
device->SetPixelShader(PS);
}
}
void setConstant(UniformType uType, const float *value, int vectors) {
const Binding &b = bindings[uType];
if (b.usage | USAGE_VS) device->SetVertexShaderConstantF (b.reg, value, vectors);
if (b.usage | USAGE_PS) device->SetPixelShaderConstantF (b.reg, value, vectors);
}
void setParam(UniformType uType, const vec4 &value, int count = 1) {
setConstant(uType, (float*)&value, count);
}
void setParam(UniformType uType, const mat4 &value, int count = 1) {
setConstant(uType, (float*)&value, count * 4);
}
void setParam(UniformType uType, const Basis &value, int count = 1) {
setConstant(uType, (float*)&value, count * 2);
}
};
// Texture
struct Texture {
LPDIRECT3DTEXTURE9 tex2D;
LPDIRECT3DCUBETEXTURE9 texCube;
int width, height, origWidth, origHeight;
TexFormat fmt;
uint32 opt;
Texture(int width, int height, uint32 opt) : tex2D(NULL), texCube(NULL), width(width), height(height), origWidth(width), origHeight(height), fmt(FMT_RGBA), opt(opt) {}
void init(void *data) {
ASSERT((opt & OPT_PROXY) == 0);
bool filter = (opt & OPT_NEAREST) == 0;
bool mipmaps = (opt & OPT_MIPMAPS) != 0;
bool cube = (opt & OPT_CUBEMAP) != 0;
bool isShadow = fmt == FMT_SHADOW;
static const struct FormatDesc {
int bpp;
D3DFORMAT format;
} formats[FMT_MAX] = {
{ 8, D3DFMT_L8 },
{ 32, D3DFMT_A8R8G8B8 },
{ 16, D3DFMT_R5G6B5 },
{ 16, D3DFMT_A1R5G5B5 },
{ 64, D3DFMT_A16B16G16R16 },
{ 64, D3DFMT_A16B16G16R16 },
{ 16, D3DFMT_D16 },
{ 32, D3DFMT_D24S8 },
{ 16, D3DFMT_D16 },
};
FormatDesc desc = formats[fmt];
if (cube) {
device->CreateCubeTexture(width, 1, 0, desc.format, D3DPOOL_MANAGED, &texCube, NULL);
} else {
device->CreateTexture(width, height, 1, 0, desc.format, D3DPOOL_MANAGED, &tex2D, NULL);
if (data) {
D3DLOCKED_RECT rect;
tex2D->LockRect(0, &rect, NULL, 0);
memcpy(rect.pBits, data, width * height * (desc.bpp / 8));
tex2D->UnlockRect(0);
}
}
}
void deinit() {
if (tex2D) tex2D->Release();
if (texCube) texCube->Release();
}
void generateMipMap() {
// TODO
}
void bind(int sampler) {
if (opt & OPT_PROXY) return;
ASSERT(tex2D || texCube);
if (Core::active.textures[sampler] != this) {
Core::active.textures[sampler] = this;
if (tex2D)
device->SetTexture(sampler, tex2D);
else if (texCube)
device->SetTexture(sampler, texCube);
}
}
void unbind(int sampler) {
if (Core::active.textures[sampler]) {
Core::active.textures[sampler] = NULL;
device->SetTexture(sampler, NULL);
}
}
void setFilterQuality(int value) {
bool filter = value > Core::Settings::LOW;
bool mipmaps = value > Core::Settings::MEDIUM;
for (int i = 0; i < sMAX; i++) {
device->SetSamplerState(i, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP);
device->SetSamplerState(i, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP);
device->SetSamplerState(i, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);
device->SetSamplerState(i, D3DSAMP_MAGFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
device->SetSamplerState(i, D3DSAMP_MINFILTER, filter ? D3DTEXF_LINEAR : D3DTEXF_POINT);
}
}
};
// Mesh
struct Mesh {
LPDIRECT3DINDEXBUFFER9 IB;
LPDIRECT3DVERTEXBUFFER9 VB;
int iCount;
int vCount;
bool dynamic;
Mesh(bool dynamic) : IB(NULL), VB(NULL), dynamic(dynamic) {}
void init(Index *indices, int iCount, ::Vertex *vertices, int vCount, int aCount) {
this->iCount = iCount;
this->vCount = vCount;
ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex));
device->CreateIndexBuffer (iCount * sizeof(indices[0]), D3DUSAGE_WRITEONLY, D3DFMT_INDEX16, D3DPOOL_MANAGED, &IB, NULL);
device->CreateVertexBuffer (vCount * sizeof(vertices[0]), D3DUSAGE_WRITEONLY, 0, D3DPOOL_MANAGED, &VB, NULL);
update(indices, iCount, vertices, vCount);
}
void deinit() {
IB->Release();
VB->Release();
}
void update(Index *indices, int iCount, ::Vertex *vertices, int vCount) {
ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex));
void* ptr;
int size;
if (indices && iCount) {
IB->Lock(0, size = iCount * sizeof(indices[0]), &ptr, 0);
memcpy(ptr, indices, size);
IB->Unlock();
}
if (vertices && vCount) {
VB->Lock(0, size = vCount * sizeof(vertices[0]), &ptr, 0);
memcpy(ptr, vertices, size);
VB->Unlock();
}
}
void bind(const MeshRange &range) const {
device->SetIndices(IB);
device->SetStreamSource(0, VB, 0, sizeof(Vertex));
}
void initNextRange(MeshRange &range, int &aIndex) const {
range.aIndex = -1;
}
};
// GLuint FBO, defaultFBO;
struct RenderTargetCache {
int count;
struct Item {
// GLuint ID;
int width;
int height;
} items[MAX_RENDER_BUFFERS];
} rtCache[2];
void init() {
memset(rtCache, 0, sizeof(rtCache));
D3DADAPTER_IDENTIFIER9 adapterInfo;
D3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &adapterInfo);
LOG("Vendor : %s\n", adapterInfo.Description);
LOG("Renderer : Direct3D 9.0c\n");
support.maxAniso = 1;
support.maxVectors = 16;
support.shaderBinary = false;
support.VAO = false;
support.depthTexture = false;
support.shadowSampler = false;
support.discardFrame = false;
support.texNPOT = false;
support.texRG = false;
support.texBorder = false;
support.maxAniso = false;
support.colorFloat = false;
support.colorHalf = false;
support.texFloatLinear = false;
support.texFloat = false;
support.texHalfLinear = false;
support.texHalf = false;
#ifdef PROFILE
support.profMarker = false;
support.profTiming = false;
#endif
const D3DVERTEXELEMENT9 VERTEX_DECL[] = {
{0, 0, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, // aCoord
{0, 8, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, // aNormal
{0, 16, D3DDECLTYPE_SHORT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, // aTexCoord
{0, 24, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0}, // aColor
{0, 28, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 1}, // aLight
D3DDECL_END()
};
device->CreateVertexDeclaration(VERTEX_DECL, &vertexDecl);
/*
if (support.maxAniso)
glGetIntegerv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &support.maxAniso);
#ifdef _GAPI_GLES
glGetIntegerv(GL_MAX_VARYING_VECTORS, &support.maxVectors);
#else
support.maxVectors = 16;
#endif
glEnable(GL_SCISSOR_TEST);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint*)&defaultFBO);
glGenFramebuffers(1, &FBO);
*/
}
void deinit() {
/*
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDeleteFramebuffers(1, &FBO);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
for (int b = 0; b < 2; b++)
for (int i = 0; i < rtCache[b].count; i++)
glDeleteRenderbuffers(1, &rtCache[b].items[i].ID);
*/
}
void beginFrame() {
device->BeginScene();
}
void endFrame() {
device->EndScene();
}
void resetState() {
device->SetVertexDeclaration(vertexDecl);
device->SetRenderState(D3DRS_ZFUNC, D3DCMP_LESSEQUAL);
device->SetRenderState(D3DRS_LIGHTING, FALSE);
device->SetRenderState(D3DRS_SCISSORTESTENABLE, TRUE);
}
int cacheRenderTarget(bool depth, int width, int height) {
RenderTargetCache &cache = rtCache[depth];
for (int i = 0; i < cache.count; i++)
if (cache.items[i].width == width && cache.items[i].height == height)
return i;
ASSERT(cache.count < MAX_RENDER_BUFFERS);
RenderTargetCache::Item &item = cache.items[cache.count];
item.width = width;
item.height = height;
/*
glGenRenderbuffers(1, &item.ID);
glBindRenderbuffer(GL_RENDERBUFFER, item.ID);
glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_RGB565 : GL_DEPTH_COMPONENT16, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0);
*/
return cache.count++;
}
void bindTarget(Texture *target, int face) {
/*
if (!target) { // may be a null
glBindFramebuffer(GL_FRAMEBUFFER, defaultFBO);
} else {
GLenum texTarget = GL_TEXTURE_2D;
if (target->opt & OPT_CUBEMAP)
texTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
bool depth = target->fmt == FMT_DEPTH || target->fmt == FMT_SHADOW;
int rtIndex = cacheRenderTarget(depth, target->width, target->height);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glFramebufferTexture2D (GL_FRAMEBUFFER, depth ? GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0, texTarget, target->ID, 0);
glFramebufferRenderbuffer (GL_FRAMEBUFFER, depth ? GL_COLOR_ATTACHMENT0 : GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rtCache[depth].items[rtIndex].ID);
}
*/
}
void discardTarget(bool color, bool depth) {}
void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {
Core::active.textures[0] = NULL;
/*
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, dst->ID);
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, x, y, width, height);
glBindTexture(GL_TEXTURE_2D, 0);
*/
}
void setVSync(bool enable) {
//
}
void waitVBlank() {}
void clear(bool color, bool depth) {
uint32 flags = (color ? D3DCLEAR_TARGET : 0) | (depth ? D3DCLEAR_ZBUFFER : 0);
device->Clear(0, NULL, flags, clearColor, 1.0f, 0);
}
void setClearColor(const vec4 &color) {
clearColor = (int(color.x * 255) << 16) |
(int(color.y * 255) << 8 ) |
(int(color.z * 255) ) |
(int(color.w * 255) << 24);
}
void setViewport(const Viewport &vp) {
D3DVIEWPORT9 dv;
dv.X = vp.x;
dv.Y = vp.y;
dv.Width = vp.width;
dv.Height = vp.height;
dv.MinZ = 0.0f;
dv.MaxZ = 1.0f;
RECT ds;
ds.left = vp.x;
ds.top = vp.y;
ds.right = vp.x + vp.width;
ds.bottom = vp.y + vp.height;
device->SetViewport(&dv);
device->SetScissorRect(&ds);
}
void setDepthTest(bool enable) {
device->SetRenderState(D3DRS_ZENABLE, enable);
}
void setDepthWrite(bool enable) {
device->SetRenderState(D3DRS_ZWRITEENABLE, enable);
}
void setColorWrite(bool r, bool g, bool b, bool a) {
device->SetRenderState(D3DRS_COLORWRITEENABLE,
(r ? D3DCOLORWRITEENABLE_RED : 0) |
(g ? D3DCOLORWRITEENABLE_GREEN : 0) |
(b ? D3DCOLORWRITEENABLE_BLUE : 0) |
(a ? D3DCOLORWRITEENABLE_ALPHA : 0));
}
void setAlphaTest(bool enable) {}
void setCullMode(int rsMask) {
cullMode = rsMask;
switch (rsMask) {
case RS_CULL_BACK : device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); break;
case RS_CULL_FRONT : device->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); break;
default : device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
}
}
void setBlendMode(int rsMask) {
blendMode = rsMask;
switch (rsMask) {
case RS_BLEND_ALPHA :
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
break;
case RS_BLEND_ADD :
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE);
break;
case RS_BLEND_MULT :
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_DESTCOLOR);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ZERO);
break;
case RS_BLEND_PREMULT :
device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
break;
default :
device->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
return;
}
device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
}
void setViewProj(const mat4 &mView, const mat4 &mProj) {
}
void DIP(Mesh *mesh, const MeshRange &range) {
device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, range.vStart, 0, mesh->vCount, range.iStart, range.iCount / 3);
}
vec4 copyPixel(int x, int y) {
ubyte4 c;
// glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, &c);
return vec4(float(c.x), float(c.y), float(c.z), float(c.w)) * (1.0f / 255.0f);
}
void initPSO(PSO *pso) {
ASSERT(pso);
ASSERT(pso && pso->data == NULL);
pso->data = &pso;
}
void deinitPSO(PSO *pso) {
ASSERT(pso);
ASSERT(pso->data != NULL);
pso->data = NULL;
}
void bindPSO(const PSO *pso) {
//
}
}
#endif

View File

@@ -306,30 +306,204 @@
namespace GAPI {
#ifndef FFP
const char SHADER_BASE[] =
#include "shaders/shader.glsl"
;
const char SHADER_WATER[] =
#include "shaders/water.glsl"
;
const char SHADER_FILTER[] =
#include "shaders/filter.glsl"
;
const char SHADER_GUI[] =
#include "shaders/gui.glsl"
;
#endif
using namespace Core;
typedef ::Vertex Vertex;
int cullMode, blendMode;
// Shader
#ifndef FFP
const char SHADER_BASE[] =
#include "shaders/shader.glsl"
;
const char SHADER_WATER[] =
#include "shaders/water.glsl"
;
const char SHADER_FILTER[] =
#include "shaders/filter.glsl"
;
const char SHADER_GUI[] =
#include "shaders/gui.glsl"
;
const char *DefineName[SD_MAX] = { SHADER_DEFINES(DECL_STR) };
#endif
struct Shader {
#ifdef FFP
void init(Core::Pass pass, int *def, int defCount) {}
void deinit() {}
void bind() {}
void setParam(UniformType uType, const vec4 &value, int count = 1) {}
void setParam(UniformType uType, const mat4 &value, int count = 1) {}
void setParam(UniformType uType, const Basis &value, int count = 1) {}
#else
uint32 ID;
int32 uID[uMAX];
void init(Core::Pass pass, int *def, int defCount) {
const char *source;
switch (pass) {
case Core::passCompose :
case Core::passShadow :
case Core::passAmbient : source = SHADER_BASE; break;
case Core::passWater : source = SHADER_WATER; break;
case Core::passFilter : source = SHADER_FILTER; break;
case Core::passGUI : source = SHADER_GUI; break;
default : ASSERT(false); LOG("! wrong pass id\n"); return;
}
char defines[1024];
sprintf(defines, "#define PASS_%s\n", passNames[pass]);
for (int i = 0; i < defCount; i++) {
#ifdef _GAPI_GLES
if (def[i] == SD_SHADOW_SAMPLER)
strcat(ext, "#extension GL_EXT_shadow_samplers : require\n");
#endif
sprintf(defines, "%s#define %s\n", defines, DefineName[def[i]]);
}
char fileName[255];
// generate shader file path
if (Core::support.shaderBinary) {
uint32 hash = fnv32(defines, strlen(defines), fnv32(source, strlen(source)));
sprintf(fileName, "%08X.xsh", hash);
}
ID = glCreateProgram();
if (!(Core::support.shaderBinary && linkBinary(fileName))) { // try to load cached shader
if (linkSource(source, defines) && Core::support.shaderBinary) { // compile shader from source and dump it into cache
#ifndef _OS_WEB
GLenum format, size;
glGetProgramiv(ID, GL_PROGRAM_BINARY_LENGTH, (GLsizei*)&size);
char *data = new char[8 + size];
glGetProgramBinary(ID, size, NULL, &format, &data[8]);
*(int*)(&data[0]) = format;
*(int*)(&data[4]) = size;
Stream::cacheWrite(fileName, data, 8 + size);
delete[] data;
#endif
}
}
Core::active.shader = this;
glUseProgram(ID);
for (int st = 0; st < sMAX; st++) {
GLint idx = glGetUniformLocation(ID, (GLchar*)SamplerName[st]);
if (idx != -1)
glUniform1iv(idx, 1, &st);
}
for (int ut = 0; ut < uMAX; ut++)
uID[ut] = glGetUniformLocation(ID, (GLchar*)UniformName[ut]);
}
void deinit() {
glDeleteProgram(ID);
}
bool linkSource(const char *text, const char *defines = "") {
#ifdef _GAPI_GLES
#define GLSL_DEFINE ""
#define GLSL_VERT ""
#define GLSL_FRAG "#extension GL_OES_standard_derivatives : enable\n"
#else
#define GLSL_DEFINE "#version 120\n"
#define GLSL_VERT ""
#define GLSL_FRAG ""
#endif
const int type[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
const char *code[2][4] = {
{ GLSL_DEFINE GLSL_VERT "#define VERTEX\n", defines, "#line 0\n", text },
{ GLSL_DEFINE GLSL_FRAG "#define FRAGMENT\n", defines, "#line 0\n", text }
};
GLchar info[1024];
for (int i = 0; i < 2; i++) {
GLuint obj = glCreateShader(type[i]);
glShaderSource(obj, 4, code[i], NULL);
glCompileShader(obj);
glGetShaderInfoLog(obj, sizeof(info), NULL, info);
if (info[0]) LOG("! shader: %s\n", info);
glAttachShader(ID, obj);
glDeleteShader(obj);
}
for (int at = 0; at < aMAX; at++)
glBindAttribLocation(ID, at, AttribName[at]);
glLinkProgram(ID);
glGetProgramInfoLog(ID, sizeof(info), NULL, info);
if (info[0]) LOG("! program: %s\n", info);
return checkLink();
}
bool linkBinary(const char *name) {
// non-async code!
char path[255];
strcpy(path, Stream::cacheDir);
strcat(path, name);
if (!Stream::exists(path))
return false;
Stream *stream = new Stream(path);
if (!stream)
return false;
GLenum size, format;
stream->read(format);
stream->read(size);
char *data = new char[size];
stream->raw(data, size);
glProgramBinary(ID, format, data, size);
delete[] data;
delete stream;
return checkLink();
}
bool checkLink() {
GLint success;
glGetProgramiv(ID, GL_LINK_STATUS, &success);
return success != 0;
}
void bind() {
if (Core::active.shader != this) {
Core::active.shader = this;
glUseProgram(ID);
}
}
void setParam(UniformType uType, const vec4 &value, int count = 1) {
if (uID[uType] != -1) glUniform4fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const mat4 &value, int count = 1) {
if (uID[uType] != -1) glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
}
void setParam(UniformType uType, const Basis &value, int count = 1) {
if (uID[uType] != -1) glUniform4fv(uID[uType], count * 2, (GLfloat*)&value);
}
#endif
};
// Texture
struct Texture {
uint32 ID;
@@ -368,7 +542,7 @@ namespace GAPI {
glTexParameteri(target, GL_TEXTURE_MIN_FILTER, filter ? (mipmaps ? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR ) : ( mipmaps ? GL_NEAREST_MIPMAP_NEAREST : GL_NEAREST ));
glTexParameteri(target, GL_TEXTURE_MAG_FILTER, filter ? GL_LINEAR : GL_NEAREST);
struct FormatDesc {
static const struct FormatDesc {
GLuint ifmt, fmt;
GLenum type;
} formats[FMT_MAX] = {
@@ -599,15 +773,6 @@ namespace GAPI {
} else
range.aIndex = -1;
}
/*
void unbind() {
if (Core::support.VAO)
glBindVertexArray(Core::active.VAO = 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, Core::active.iBuffer = 0);
glBindBuffer(GL_ARRAY_BUFFER, Core::active.vBuffer = 0);
}
*/
};
@@ -813,6 +978,10 @@ namespace GAPI {
glDeleteRenderbuffers(1, &rtCache[b].items[i].ID);
}
void beginFrame() {}
void endFrame() {}
void resetState() {
if (Core::support.VAO)
glBindVertexArray(0);
@@ -960,14 +1129,14 @@ namespace GAPI {
#endif
}
void DIP(int iStart, int iCount, Index *iBuffer) {
void DIP(Mesh *mesh, const MeshRange &range) {
#ifdef FFP
mat4 m = mView * mModel;
glMatrixMode(GL_MODELVIEW);
glLoadMatrixf((GLfloat*)&m);
#endif
glDrawElements(GL_TRIANGLES, iCount, GL_UNSIGNED_SHORT, iBuffer + iStart);
glDrawElements(GL_TRIANGLES, range.iCount, GL_UNSIGNED_SHORT, mesh->iBuffer + range.iStart);
}
vec4 copyPixel(int x, int y) {

View File

@@ -289,6 +289,10 @@ namespace GAPI {
delete[] cmdBuf;
}
void beginFrame() {}
void endFrame() {}
void resetState() {}
void bindTarget(Texture *texture, int face) {
@@ -377,13 +381,13 @@ namespace GAPI {
sceGumLoadMatrix((ScePspFMatrix4*)&mView);
}
void DIP(int iStart, int iCount, Index *iBuffer) {
void DIP(Mesh *mesh, const MeshRange &range) {
mat4 m = mModel;
m.scale(vec3(32767.0f));
sceGumMatrixMode(GU_MODEL);
sceGumLoadMatrix((ScePspFMatrix4*)&m);
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_16BIT | GU_COLOR_8888 | GU_NORMAL_16BIT | GU_VERTEX_16BIT | GU_INDEX_16BIT | GU_TRANSFORM_3D, iCount, active.iBuffer + iStart, active.vBuffer);
sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_16BIT | GU_COLOR_8888 | GU_NORMAL_16BIT | GU_VERTEX_16BIT | GU_INDEX_16BIT | GU_TRANSFORM_3D, range.iCount, mesh->iBuffer + range.iStart, mesh->vBuffer);
}
vec4 copyPixel(int x, int y) {

View File

@@ -1107,7 +1107,7 @@ struct Inventory {
for (int i = 0; i < COUNT(background); i++)
if (!background[i])
background[i] = new Texture(INVENTORY_BG_SIZE, INVENTORY_BG_SIZE, FMT_RGBA);
background[i] = new Texture(INVENTORY_BG_SIZE, INVENTORY_BG_SIZE, FMT_RGBA, OPT_TARGET);
return background[0];
}
@@ -1522,12 +1522,12 @@ struct Inventory {
Core::whiteTex->bind(sShadow);
game->setShader(Core::passCompose, Shader::ENTITY, false, false);
vec3 ambient[6] = {
vec3(0.4f), vec3(0.2f), vec3(0.4f), vec3(0.5f), vec3(0.4f), vec3(0.6f)
vec4 ambient[6] = {
vec4(0.4f), vec4(0.2f), vec4(0.4f), vec4(0.5f), vec4(0.4f), vec4(0.6f)
};
for (int i = 0; i < MAX_LIGHTS; i++) {
Core::lightPos[i] = vec3(0, 0, 0);
Core::lightPos[i] = vec4(0, 0, 0, 0);
Core::lightColor[i] = vec4(0, 0, 0, 1);
}

View File

@@ -11,7 +11,11 @@
#include "trigger.h"
#include "inventory.h"
#ifdef _DEBUG
#if defined(_DEBUG) && defined(_GAPI_GL) && !defined(_GAPI_GLES)
#define DEBUG_RENDER
#endif
#ifdef DEBUG_RENDER
#include "debug.h"
#endif
@@ -1354,7 +1358,7 @@ struct Level : IGame {
}
setRoomParams(roomIndex, Shader::ROOM, 1.0f, intensityf(level.rooms[roomIndex].ambient), 0.0f, 1.0f, transp == 1);
Shader *sh = Core::active.shader;
GAPI::Shader *sh = Core::active.shader;
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
@@ -1391,7 +1395,7 @@ struct Level : IGame {
continue;
setRoomParams(roomIndex, Shader::SPRITE, 1.0f, 1.0f, 0.0f, 1.0f, true);
Shader *sh = Core::active.shader;
GAPI::Shader *sh = Core::active.shader;
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
@@ -1456,7 +1460,7 @@ struct Level : IGame {
setMainLight(controller);
} else { // sprite
Core::lightPos[0] = vec3(0);
Core::lightPos[0] = vec4(0, 0, 0, 0);
Core::lightColor[0] = vec4(0, 0, 0, 1);
}
@@ -1729,7 +1733,7 @@ struct Level : IGame {
bool checkPortal(const TR::Room &room, const TR::Room::Portal &portal, const vec4 &viewPort, vec4 &clipPort) {
vec3 n = portal.normal;
vec3 v = Core::viewPos - (room.getOffset() + portal.vertices[0]);
vec3 v = Core::viewPos.xyz() - (room.getOffset() + portal.vertices[0]);
if (n.dot(v) <= 0.0f)
return false;
@@ -1976,7 +1980,7 @@ struct Level : IGame {
Core::mLightProj[0] = bias * (Core::mProj * Core::mView);
camera->frustum->pos = Core::viewPos;
camera->frustum->pos = Core::viewPos.xyz();
camera->frustum->calcPlanes(Core::mViewProj);
setup();
@@ -2124,7 +2128,7 @@ struct Level : IGame {
Core::eye = oldEye;
}
#ifdef _DEBUG
#ifdef DEBUG_RENDER
void renderDebug() {
if (level.isTitle() || inventory.titleTimer > 1.0f) return;
@@ -2240,7 +2244,7 @@ struct Level : IGame {
// Debug::Level::debugBoxes(level, lara->dbgBoxes, lara->dbgBoxesCount);
Core::setDepthTest(true);
Core::setBlendMode(bmNone);
/*
/*// render ambient cube
Core::validateRenderState();
static int dbg_ambient = 0;
@@ -2372,7 +2376,7 @@ struct Level : IGame {
if (ambientCache)
ambientCache->processQueue();
if (shadow)
if (shadow && player)
renderShadows(player->getRoomIndex());
}

View File

@@ -30,8 +30,7 @@ struct Mesh : GAPI::Mesh {
}
void render(const MeshRange &range) {
bind(range);
Core::DIP(range.iStart, range.iCount, iBuffer);
Core::DIP(this, range);
}
};

View File

@@ -106,7 +106,7 @@
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>openvr_api.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>openvr_api.lib;d3d9.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Editor|Win32'">
@@ -149,7 +149,7 @@
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>wcrt.lib;openvr_api.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>wcrt.lib;openvr_api.lib;d3d9.lib;opengl32.lib;winmm.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<IgnoreAllDefaultLibraries>true</IgnoreAllDefaultLibraries>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
@@ -199,6 +199,7 @@
<ClInclude Include="..\..\collision.h" />
<ClInclude Include="..\..\controller.h" />
<ClInclude Include="..\..\core.h" />
<ClInclude Include="..\..\gapi_d3d9.h" />
<ClInclude Include="..\..\gapi_gl.h" />
<ClInclude Include="..\..\gapi_gu.h" />
<ClInclude Include="..\..\gapi_gx.h" />

View File

@@ -41,6 +41,7 @@
<ClInclude Include="..\..\gapi_gu.h" />
<ClInclude Include="..\..\gapi_vk.h" />
<ClInclude Include="..\..\gapi_gx.h" />
<ClInclude Include="..\..\gapi_d3d9.h" />
<ClInclude Include="..\..\libs\minimp3\minimp3.h">
<Filter>libs\minimp3</Filter>
</ClInclude>

View File

@@ -401,6 +401,90 @@ void sndInit(HWND hwnd) {
}
}
HWND hWnd;
#ifdef _GAPI_GL
HDC hDC;
HGLRC hRC;
void ContextCreate() {
hDC = GetDC(hWnd);
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.cColorBits = 32;
pfd.cRedBits = 8;
pfd.cGreenBits = 8;
pfd.cBlueBits = 8;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
int format = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, format, &pfd);
hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
}
void ContextDelete() {
wglMakeCurrent(0, 0);
wglDeleteContext(hRC);
ReleaseDC(hWnd, hDC);
}
void ContextResize() {}
void ContextSwap() {
SwapBuffers(hDC);
}
#else
D3DPRESENT_PARAMETERS d3dpp;
LPDIRECT3D9 D3D;
LPDIRECT3DDEVICE9 device;
void ContextCreate() {
memset(&d3dpp, 0, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferWidth = 1;
d3dpp.BackBufferHeight = 1;
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
if (!(D3D = Direct3DCreate9(D3D_SDK_VERSION))) {
LOG("! cant't initialize DirectX");
return;
}
if (!SUCCEEDED(D3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &device))) {
LOG("! can't create device");
}
}
void ContextDelete() {
GAPI::deinit();
if (device) device->Release();
if (D3D) D3D->Release();
}
void ContextResize() {
d3dpp.BackBufferWidth = Core::width;
d3dpp.BackBufferHeight = Core::height;
device->Reset(&d3dpp);
}
void ContextSwap() {
if (device->Present(NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST)
ContextResize();
}
#endif
static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch (msg) {
@@ -413,6 +497,7 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
case WM_SIZE:
Core::width = LOWORD(lParam);
Core::height = HIWORD(lParam);
ContextResize();
break;
case WM_DESTROY:
PostQuitMessage(0);
@@ -487,32 +572,6 @@ static LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lPara
return 0;
}
HGLRC glInit(HDC hDC) {
PIXELFORMATDESCRIPTOR pfd;
memset(&pfd, 0, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.cColorBits = 32;
pfd.cRedBits = 8;
pfd.cGreenBits = 8;
pfd.cBlueBits = 8;
pfd.cAlphaBits = 8;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
int format = ChoosePixelFormat(hDC, &pfd);
SetPixelFormat(hDC, format, &pfd);
HGLRC hRC = wglCreateContext(hDC);
wglMakeCurrent(hDC, hRC);
return hRC;
}
void glFree(HGLRC hRC) {
wglMakeCurrent(0, 0);
wglDeleteContext(hRC);
}
#ifdef VR_SUPPORT
vr::IVRSystem *hmd;
vr::TrackedDevicePose_t tPose[vr::k_unMaxTrackedDeviceCount];
@@ -645,10 +704,9 @@ int main(int argc, char** argv) {
RECT r = { 0, 0, 1280, 720 };
AdjustWindowRect(&r, WS_OVERLAPPEDWINDOW, false);
HWND hWnd = CreateWindow("static", "OpenLara", WS_OVERLAPPEDWINDOW, 0, 0, r.right - r.left, r.bottom - r.top, 0, 0, 0, 0);
hWnd = CreateWindow("static", "OpenLara", WS_OVERLAPPEDWINDOW, 0, 0, r.right - r.left, r.bottom - r.top, 0, 0, 0, 0);
HDC hDC = GetDC(hWnd);
HGLRC hRC = glInit(hDC);
ContextCreate();
#ifdef VR_SUPPORT
vrInit();
@@ -694,7 +752,7 @@ int main(int argc, char** argv) {
vrCompose();
#endif
Core::waitVBlank();
SwapBuffers(hDC);
ContextSwap();
}
#ifdef _DEBUG
Sleep(20);
@@ -709,8 +767,7 @@ int main(int argc, char** argv) {
vrFree();
#endif
glFree(hRC);
ReleaseDC(hWnd, hDC);
ContextDelete();
DestroyWindow(hWnd);
#ifdef _DEBUG

View File

@@ -3,192 +3,32 @@
#include "core.h"
struct Shader {
vec4 params[uMAX][4];
struct Shader : GAPI::Shader {
enum Type {
DEFAULT = 0,
/* shader */ SPRITE = 0, FLASH = 1, ROOM = 2, ENTITY = 3, MIRROR = 4,
/* filter */ FILTER_DOWNSAMPLE = 1, FILTER_GRAYSCALE = 2, FILTER_BLUR = 3, FILTER_MIXER = 4, FILTER_EQUIRECTANGULAR = 5,
/* filter */ FILTER_DOWNSAMPLE = 1, FILTER_GRAYSCALE = 2, FILTER_BLUR = 3, FILTER_EQUIRECTANGULAR = 4,
/* water */ WATER_DROP = 0, WATER_STEP = 1, WATER_CAUSTICS = 2, WATER_MASK = 3, WATER_COMPOSE = 4,
MAX = 6
};
#ifdef FFP
Shader(const char *source, const char *defines = "") {}
virtual ~Shader() {}
void bind() {}
void setParam(UniformType uType, const int &value, int count = 1) {}
void setParam(UniformType uType, const float &value, int count = 1) {}
void setParam(UniformType uType, const vec2 &value, int count = 1) {}
void setParam(UniformType uType, const vec3 &value, int count = 1) {}
void setParam(UniformType uType, const vec4 &value, int count = 1) {}
void setParam(UniformType uType, const mat4 &value, int count = 1) {}
void setParam(UniformType uType, const Basis &value, int count = 1) {}
#else
uint32 ID;
int32 uID[uMAX];
Shader(const char *source, const char *defines = "") {
char fileName[255];
// generate shader file path
if (Core::support.shaderBinary) {
uint32 hash = fnv32(defines, strlen(defines), fnv32(source, strlen(source)));
sprintf(fileName, "%08X.xsh", hash);
}
ID = glCreateProgram();
if (!(Core::support.shaderBinary && linkBinary(fileName))) // try to load cached shader
if (linkSource(source, defines) && Core::support.shaderBinary) { // compile shader from source and dump it into cache
#ifndef _OS_WEB
GLenum format, size;
glGetProgramiv(ID, GL_PROGRAM_BINARY_LENGTH, (GLsizei*)&size);
char *data = new char[8 + size];
glGetProgramBinary(ID, size, NULL, &format, &data[8]);
*(int*)(&data[0]) = format;
*(int*)(&data[4]) = size;
Stream::cacheWrite(fileName, data, 8 + size);
delete[] data;
#endif
}
init();
}
bool linkSource(const char *text, const char *defines = "") {
#ifdef _GAPI_GLES
#define GLSL_DEFINE ""
#define GLSL_VERT ""
#define GLSL_FRAG "#extension GL_OES_standard_derivatives : enable\n"
#else
#define GLSL_DEFINE "#version 120\n"
#define GLSL_VERT ""
#define GLSL_FRAG ""
#endif
const int type[2] = { GL_VERTEX_SHADER, GL_FRAGMENT_SHADER };
const char *code[2][4] = {
{ GLSL_DEFINE GLSL_VERT "#define VERTEX\n", defines, "#line 0\n", text },
{ GLSL_DEFINE GLSL_FRAG "#define FRAGMENT\n", defines, "#line 0\n", text }
};
GLchar info[1024];
for (int i = 0; i < 2; i++) {
GLuint obj = glCreateShader(type[i]);
glShaderSource(obj, 4, code[i], NULL);
glCompileShader(obj);
glGetShaderInfoLog(obj, sizeof(info), NULL, info);
if (info[0]) LOG("! shader: %s\n", info);
glAttachShader(ID, obj);
glDeleteShader(obj);
}
for (int at = 0; at < aMAX; at++)
glBindAttribLocation(ID, at, AttribName[at]);
glLinkProgram(ID);
glGetProgramInfoLog(ID, sizeof(info), NULL, info);
if (info[0]) LOG("! program: %s\n", info);
return checkLink();
}
bool linkBinary(const char *name) {
// non-async code!
char path[255];
strcpy(path, Stream::cacheDir);
strcat(path, name);
if (!Stream::exists(path))
return false;
Stream *stream = new Stream(path);
if (!stream)
return false;
GLenum size, format;
stream->read(format);
stream->read(size);
char *data = new char[size];
stream->raw(data, size);
glProgramBinary(ID, format, data, size);
delete[] data;
delete stream;
return checkLink();
}
bool checkLink() {
GLint success;
glGetProgramiv(ID, GL_LINK_STATUS, &success);
return success != 0;
Shader(Core::Pass pass, int *def, int defCount) : GAPI::Shader() {
init(pass, def, defCount);
}
virtual ~Shader() {
glDeleteProgram(ID);
deinit();
}
void init() {
Core::active.shader = this;
glUseProgram(ID);
for (int st = 0; st < sMAX; st++) {
GLint idx = glGetUniformLocation(ID, (GLchar*)SamplerName[st]);
if (idx != -1)
glUniform1iv(idx, 1, &st);
}
for (int ut = 0; ut < uMAX; ut++)
uID[ut] = glGetUniformLocation(ID, (GLchar*)UniformName[ut]);
memset(params, 0, sizeof(params));
}
void bind() {
if (Core::active.shader != this) {
Core::active.shader = this;
glUseProgram(ID);
}
void setup() {
bind();
setParam(uViewProj, Core::mViewProj);
setParam(uLightProj, Core::mLightProj[0], Core::settings.detail.shadows > Core::Settings::Quality::MEDIUM ? SHADOW_OBJ_MAX : 1);
setParam(uViewPos, Core::viewPos);
setParam(uParam, Core::params);
setParam(uFogParams, Core::fogParams);
}
void setParam(UniformType uType, const int &value, int count = 1) {
if (uID[uType] != -1) glUniform1iv(uID[uType], count, (GLint*)&value);
}
void setParam(UniformType uType, const float &value, int count = 1) {
if (uID[uType] != -1) glUniform1fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const vec2 &value, int count = 1) {
if (uID[uType] != -1) glUniform2fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const vec3 &value, int count = 1) {
if (uID[uType] != -1) glUniform3fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const vec4 &value, int count = 1) {
if (uID[uType] != -1) glUniform4fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const mat4 &value, int count = 1) {
if (uID[uType] != -1) glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
}
void setParam(UniformType uType, const Basis &value, int count = 1) {
if (uID[uType] != -1) glUniform4fv(uID[uType], count * 2, (GLfloat*)&value);
}
#endif
};
#endif

81
src/shaders/base.hlsl Normal file
View File

@@ -0,0 +1,81 @@
#define MAX_LIGHTS 4
#define MAX_CONTACTS 15
struct VS_INPUT {
float4 aCoord : POSITION;
float4 aNormal : NORMAL;
float4 aTexCoord : TEXCOORD0;
float4 aColor : COLOR0;
float4 aLight : COLOR1;
};
struct VS_OUTPUT {
float4 wPos : POSITION;
float3 vCoord : TEXCOORD2;
float4 vTexCoord : TEXCOORD0;
float4 vDiffuse : COLOR0;
float4 vNormal : NORMAL;
float4 vViewVec : TEXCOORD1;
float3 vAmbient : COLOR1;
float4 vLightMap : COLOR2;
float4 vLight : COLOR3;
};
float4 uParam : register( c0 );
float4 uTexParam : register( c1 );
float4x4 uViewProj : register( c2 );
float4 uBasis[32 * 2] : register( c6 );
float4x4 uLightProj : register( c70 );
float4 uMaterial : register( c102 );
float4 uAmbient[6] : register( c103 );
float4 uFogParams : register( c109 );
float4 uViewPos : register( c110 );
float4 uLightPos[MAX_LIGHTS] : register( c111 );
float4 uLightColor[MAX_LIGHTS] : register( c115 );
float4 uRoomSize : register( c119 );
float4 uPosScale[2] : register( c120 );
float4 uContacts[MAX_CONTACTS] : register( c122 );
#ifdef VERTEX
float3 mulQuat(float4 q, float3 v) {
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
}
float3 mulBasis(float4 rot, float3 pos, float3 v) {
return mulQuat(rot, v) + pos;
}
VS_OUTPUT main(VS_INPUT In) {
VS_OUTPUT Out;
int index = int(In.aCoord.w * 2.0);
float4 rBasisRot = uBasis[index];
float4 rBasisPos = uBasis[index + 1];
Out.vCoord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz);
Out.wPos = mul(uViewProj, float4(Out.vCoord, rBasisPos.w));
Out.vTexCoord = In.aTexCoord * (1.0 / 32767.0);
Out.vTexCoord.xy *= Out.vTexCoord.zw;
Out.vDiffuse = float4(In.aColor.xyz * In.aLight.xyz, 1.0);
Out.vNormal = In.aNormal;
Out.vViewVec = float4(uViewPos.xyz - Out.vCoord, 0.0);
Out.vAmbient = float3(0.2, 0.2, 0.2);
Out.vLightMap = float4(1.0, 1.0, 1.0, 0.0);
Out.vLight = float4(0.5, 0.5, 0.5, 0.5);
return Out;
}
#else // PIXEL
sampler sDiffuse : register(s0);
sampler sNormal : register(s1);
sampler sReflect : register(s2);
sampler sShadow : register(s3);
sampler sEnvironment : register(s4);
sampler sMask : register(s5);
float4 main(VS_OUTPUT In) : COLOR0 {
return (In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy / In.vTexCoord.zw)).bgra;
}
#endif

View File

@@ -0,0 +1,9 @@
@echo off
fxc /nologo /T vs_3_0 /O3 /Vn BASE_VS /Fh base_vs.h base.hlsl /DVERTEX
fxc /nologo /T ps_3_0 /O3 /Vn BASE_PS /Fh base_ps.h base.hlsl /DPIXEL
fxc /nologo /T vs_3_0 /O3 /Vn WATER_VS /Fh water_vs.h water.hlsl /DVERTEX
fxc /nologo /T ps_3_0 /O3 /Vn WATER_PS /Fh water_ps.h water.hlsl /DPIXEL
fxc /nologo /T vs_3_0 /O3 /Vn FILTER_VS /Fh filter_vs.h filter.hlsl /DVERTEX
fxc /nologo /T ps_3_0 /O3 /Vn FILTER_PS /Fh filter_ps.h filter.hlsl /DPIXEL
fxc /nologo /T vs_3_0 /O3 /Vn GUI_VS /Fh gui_vs.h gui.hlsl /DVERTEX
fxc /nologo /T ps_3_0 /O3 /Vn GUI_PS /Fh gui_ps.h gui.hlsl /DPIXEL

View File

@@ -57,10 +57,6 @@ uniform vec4 uParam;
return color;
}
vec4 mixer() { // uParam (lerp factor from diffuse to normal textures, multiply, unused, unused)
return mix(texture2D(sDiffuse, vTexCoord), texture2D(sNormal, vTexCoord), uParam.x) * uParam.y;
}
#ifdef FILTER_EQUIRECTANGULAR
uniform samplerCube sEnvironment;
@@ -86,10 +82,6 @@ uniform vec4 uParam;
return blur();
#endif
#ifdef FILTER_MIXER
return mixer();
#endif
#ifdef FILTER_EQUIRECTANGULAR
return equirectangular();
#endif

81
src/shaders/filter.hlsl Normal file
View File

@@ -0,0 +1,81 @@
#define MAX_LIGHTS 4
#define MAX_CONTACTS 15
struct VS_INPUT {
float4 aCoord : POSITION;
float4 aNormal : NORMAL;
float4 aTexCoord : TEXCOORD0;
float4 aColor : COLOR0;
float4 aLight : COLOR1;
};
struct VS_OUTPUT {
float4 wPos : POSITION;
float3 vCoord : TEXCOORD2;
float4 vTexCoord : TEXCOORD0;
float4 vDiffuse : COLOR0;
float4 vNormal : NORMAL;
float4 vViewVec : TEXCOORD1;
float3 vAmbient : COLOR1;
float4 vLightMap : COLOR2;
float4 vLight : COLOR3;
};
float4 uParam : register( c0 );
float4 uTexParam : register( c1 );
float4x4 uViewProj : register( c2 );
float4 uBasis[32 * 2] : register( c6 );
float4x4 uLightProj : register( c70 );
float4 uMaterial : register( c102 );
float4 uAmbient[6] : register( c103 );
float4 uFogParams : register( c109 );
float4 uViewPos : register( c110 );
float4 uLightPos[MAX_LIGHTS] : register( c111 );
float4 uLightColor[MAX_LIGHTS] : register( c115 );
float4 uRoomSize : register( c119 );
float4 uPosScale[2] : register( c120 );
float4 uContacts[MAX_CONTACTS] : register( c122 );
#ifdef VERTEX
float3 mulQuat(float4 q, float3 v) {
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
}
float3 mulBasis(float4 rot, float3 pos, float3 v) {
return mulQuat(rot, v) + pos;
}
VS_OUTPUT main(VS_INPUT In) {
VS_OUTPUT Out;
int index = int(In.aCoord.w * 2.0);
float4 rBasisRot = uBasis[index];
float4 rBasisPos = uBasis[index + 1];
Out.vCoord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz);
Out.wPos = mul(uViewProj, float4(Out.vCoord, rBasisPos.w));
Out.vTexCoord = In.aTexCoord * (1.0 / 32767.0);
Out.vTexCoord.xy *= Out.vTexCoord.zw;
Out.vDiffuse = float4(In.aColor.xyz * In.aLight.xyz, 1.0);
Out.vNormal = In.aNormal;
Out.vViewVec = float4(uViewPos.xyz - Out.vCoord, 0.0);
Out.vAmbient = float3(0.2, 0.2, 0.2);
Out.vLightMap = float4(1.0, 1.0, 1.0, 0.0);
Out.vLight = float4(0.5, 0.5, 0.5, 0.5);
return Out;
}
#else // PIXEL
sampler sDiffuse : register(s0);
sampler sNormal : register(s1);
sampler sReflect : register(s2);
sampler sShadow : register(s3);
sampler sEnvironment : register(s4);
sampler sMask : register(s5);
float4 main(VS_OUTPUT In) : COLOR0 {
return (In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy / In.vTexCoord.zw)).bgra;
}
#endif

49
src/shaders/gui.hlsl Normal file
View File

@@ -0,0 +1,49 @@
#define MAX_LIGHTS 4
#define MAX_CONTACTS 15
struct VS_INPUT {
float4 aCoord : POSITION;
float4 aNormal : NORMAL;
float4 aTexCoord : TEXCOORD0;
float4 aColor : COLOR0;
float4 aLight : COLOR1;
};
float4 uParam : register( c0 );
float4 uTexParam : register( c1 );
float4x4 uViewProj : register( c2 );
float4 uBasis[32 * 2] : register( c6 );
float4x4 uLightProj : register( c70 );
float4 uMaterial : register( c102 );
float4 uAmbient[6] : register( c103 );
float4 uFogParams : register( c109 );
float4 uViewPos : register( c110 );
float4 uLightPos[MAX_LIGHTS] : register( c111 );
float4 uLightColor[MAX_LIGHTS] : register( c115 );
float4 uRoomSize : register( c119 );
float4 uPosScale[2] : register( c120 );
float4 uContacts[MAX_CONTACTS] : register( c122 );
struct VS_OUTPUT {
float4 wPos : POSITION;
float2 vTexCoord : TEXCOORD0;
float4 vDiffuse : COLOR0;
};
#ifdef VERTEX
VS_OUTPUT main(VS_INPUT In) {
VS_OUTPUT Out;
Out.wPos = mul(uViewProj, float4(In.aCoord.xy * uPosScale[0].zw + uPosScale[0].xy, 0.0, 1.0));
Out.vTexCoord = In.aTexCoord.xy * (1.0 / 32767.0);
Out.vDiffuse = In.aLight * uMaterial;
return Out;
}
#else // PIXEL
sampler sDiffuse : register(s0);
float4 main(VS_OUTPUT In) : COLOR0 {
return float4(1.0, 1.0, 1.0, 1.0);//(In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy)).bgra;
}
#endif

View File

@@ -4,6 +4,11 @@ R"====(
precision highp float;
#endif
#define MAX_LIGHTS 4
#define MAX_CONTACTS 15
#define WATER_FOG_DIST (1.0 / (6.0 * 1024.0))
#define UNDERWATER_COLOR vec3(0.6, 0.9, 0.9)
#if (defined(PASS_AMBIENT) || defined(PASS_COMPOSE)) && !defined(TYPE_FLASH)
varying vec3 vCoord;
#endif
@@ -15,11 +20,18 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - trapezoidal correction
#endif
#ifdef OPT_SHADOW
#ifdef OPT_SHADOW_HIGH
#define SHADOW_OBJ_MAX 8
#define SHADOW_TEXEL vec3(1.0 / 512.0, 1.0 / 256.0, 0.0)
#else
#define SHADOW_OBJ_MAX 1
#define SHADOW_TEXEL vec3(1.0 / 1024.0, 1.0 / 1024.0, 0.0)
#endif
uniform mat4 uLightProj[SHADOW_OBJ_MAX];
#endif
uniform mat4 uViewProj;
uniform vec3 uViewPos;
uniform vec4 uViewPos;
uniform vec4 uParam; // x - time, y - water height, z - clip plane sign, w - clip plane height
uniform vec4 uLightPos[MAX_LIGHTS];
@@ -53,14 +65,14 @@ uniform vec4 uFogParams;
#endif
#ifdef OPT_AMBIENT
uniform vec3 uAmbient[6];
uniform vec4 uAmbient[6];
vec3 calcAmbient(vec3 n) {
vec3 sqr = n * n;
vec3 pos = step(0.0, n);
return sqr.x * mix(uAmbient[1], uAmbient[0], pos.x) +
sqr.y * mix(uAmbient[3], uAmbient[2], pos.y) +
sqr.z * mix(uAmbient[5], uAmbient[4], pos.z);
return sqr.x * mix(uAmbient[1].xyz, uAmbient[0].xyz, pos.x) +
sqr.y * mix(uAmbient[3].xyz, uAmbient[2].xyz, pos.y) +
sqr.z * mix(uAmbient[5].xyz, uAmbient[4].xyz, pos.z);
}
#endif
@@ -93,14 +105,14 @@ uniform vec4 uFogParams;
vec4 coord;
coord.w = rBasisPos.w; // visible flag
#if defined(TYPE_SPRITE) && defined(ALIGN_SPRITES)
#if defined(TYPE_SPRITE)
coord.xyz = mulBasis(rBasisRot, rBasisPos.xyz + aCoord.xyz, vec3(aTexCoord.z, aTexCoord.w, 0.0) * 32767.0);
#else
coord.xyz = mulBasis(rBasisRot, rBasisPos.xyz, aCoord.xyz);
#endif
#ifndef PASS_SHADOW
vViewVec = vec4((uViewPos - coord.xyz) * uFogParams.w, coord.y * uParam.z);
vViewVec = vec4((uViewPos.xyz - coord.xyz) * uFogParams.w, coord.y * uParam.z);
#endif
#ifdef PASS_AMBIENT
@@ -120,7 +132,7 @@ uniform vec4 uFogParams;
if (uViewPos.y < uParam.y)
d = abs((coord.y - uParam.y) / normalize(vViewVec.xyz).y);
else
d = length(uViewPos - coord.xyz);
d = length(uViewPos.xyz - coord.xyz);
fog = d * WATER_FOG_DIST;
#else
fog = length(vViewVec.xyz);

View File

@@ -4,6 +4,9 @@ R"====(
precision highp float;
#endif
#define WATER_FOG_DIST (1.0 / (6.0 * 1024.0))
#define UNDERWATER_COLOR vec3(0.6, 0.9, 0.9)
varying vec3 vCoord;
varying vec2 vTexCoord;
varying vec4 vProjCoord;
@@ -12,10 +15,10 @@ varying vec4 vNewPos;
varying vec3 vViewVec;
varying vec3 vLightVec;
uniform vec3 uViewPos;
uniform vec4 uViewPos;
uniform mat4 uViewProj;
uniform vec4 uLightPos;
uniform vec3 uPosScale[2];
uniform vec4 uPosScale[2];
uniform vec4 uTexParam;
uniform vec4 uParam;
@@ -29,11 +32,7 @@ uniform sampler2D sNormal;
attribute vec4 aCoord;
void main() {
#ifdef WATER_USE_GRID
vec3 coord = aCoord.xyz;
#else
vec3 coord = aCoord.xyz * (1.0 / 32767.0);
#endif
vec3 coord = aCoord.xyz * (1.0 / 32767.0);
vTexCoord = (coord.xy * 0.5 + 0.5) * uTexParam.zw;
@@ -41,14 +40,7 @@ uniform sampler2D sNormal;
float height = 0.0;
#ifdef WATER_COMPOSE
#ifdef WATER_USE_GRID
vTexCoord = (coord.xy * (1.0 / 48.0) * 0.5 + 0.5) * uTexParam.zw;
height = clamp(texture2D(sNormal, vTexCoord).x * 2.0, -0.1, 0.1);
#endif
#endif
vCoord = vec3(coord.x, height, coord.y) * uPosScale[1] + uPosScale[0];
vCoord = vec3(coord.x, height, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz;
vec4 cp = uViewProj * vec4(vCoord, 1.0);
@@ -76,7 +68,7 @@ uniform sampler2D sNormal;
gl_Position = vec4(coord.xyz, 1.0);
#endif
#endif
vViewVec = uViewPos - vCoord.xyz;
vViewVec = uViewPos.xyz - vCoord.xyz;
vLightVec = uLightPos.xyz - vCoord.xyz;
}
#else

81
src/shaders/water.hlsl Normal file
View File

@@ -0,0 +1,81 @@
#define MAX_LIGHTS 4
#define MAX_CONTACTS 15
struct VS_INPUT {
float4 aCoord : POSITION;
float4 aNormal : NORMAL;
float4 aTexCoord : TEXCOORD0;
float4 aColor : COLOR0;
float4 aLight : COLOR1;
};
struct VS_OUTPUT {
float4 wPos : POSITION;
float3 vCoord : TEXCOORD2;
float4 vTexCoord : TEXCOORD0;
float4 vDiffuse : COLOR0;
float4 vNormal : NORMAL;
float4 vViewVec : TEXCOORD1;
float3 vAmbient : COLOR1;
float4 vLightMap : COLOR2;
float4 vLight : COLOR3;
};
float4 uParam : register( c0 );
float4 uTexParam : register( c1 );
float4x4 uViewProj : register( c2 );
float4 uBasis[32 * 2] : register( c6 );
float4x4 uLightProj : register( c70 );
float4 uMaterial : register( c102 );
float4 uAmbient[6] : register( c103 );
float4 uFogParams : register( c109 );
float4 uViewPos : register( c110 );
float4 uLightPos[MAX_LIGHTS] : register( c111 );
float4 uLightColor[MAX_LIGHTS] : register( c115 );
float4 uRoomSize : register( c119 );
float4 uPosScale[2] : register( c120 );
float4 uContacts[MAX_CONTACTS] : register( c122 );
#ifdef VERTEX
float3 mulQuat(float4 q, float3 v) {
return v + 2.0 * cross(q.xyz, cross(q.xyz, v) + v * q.w);
}
float3 mulBasis(float4 rot, float3 pos, float3 v) {
return mulQuat(rot, v) + pos;
}
VS_OUTPUT main(VS_INPUT In) {
VS_OUTPUT Out;
int index = int(In.aCoord.w * 2.0);
float4 rBasisRot = uBasis[index];
float4 rBasisPos = uBasis[index + 1];
Out.vCoord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz);
Out.wPos = mul(uViewProj, float4(Out.vCoord, rBasisPos.w));
Out.vTexCoord = In.aTexCoord * (1.0 / 32767.0);
Out.vTexCoord.xy *= Out.vTexCoord.zw;
Out.vDiffuse = float4(In.aColor.xyz * In.aLight.xyz, 1.0);
Out.vNormal = In.aNormal;
Out.vViewVec = float4(uViewPos.xyz - Out.vCoord, 0.0);
Out.vAmbient = float3(0.2, 0.2, 0.2);
Out.vLightMap = float4(1.0, 1.0, 1.0, 0.0);
Out.vLight = float4(0.5, 0.5, 0.5, 0.5);
return Out;
}
#else // PIXEL
sampler sDiffuse : register(s0);
sampler sNormal : register(s1);
sampler sReflect : register(s2);
sampler sShadow : register(s3);
sampler sEnvironment : register(s4);
sampler sMask : register(s5);
float4 main(VS_OUTPUT In) : COLOR0 {
return (In.vDiffuse * tex2D(sDiffuse, In.vTexCoord.xy / In.vTexCoord.zw)).bgra;
}
#endif