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:
111
src/cache.h
111
src/cache.h
@@ -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);
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
84
src/core.h
84
src/core.h
@@ -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;
|
||||
|
@@ -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
533
src/gapi_d3d9.h
Normal 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
|
229
src/gapi_gl.h
229
src/gapi_gl.h
@@ -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) {
|
||||
|
@@ -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) {
|
||||
|
@@ -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);
|
||||
}
|
||||
|
||||
|
22
src/level.h
22
src/level.h
@@ -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());
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -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" />
|
||||
|
@@ -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>
|
||||
|
@@ -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
|
||||
|
174
src/shader.h
174
src/shader.h
@@ -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
81
src/shaders/base.hlsl
Normal 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
|
9
src/shaders/compile_dx9.bat
Normal file
9
src/shaders/compile_dx9.bat
Normal 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
|
@@ -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
81
src/shaders/filter.hlsl
Normal 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
49
src/shaders/gui.hlsl
Normal 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
|
@@ -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);
|
||||
|
@@ -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
81
src/shaders/water.hlsl
Normal 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
|
Reference in New Issue
Block a user