mirror of
https://github.com/XProger/OpenLara.git
synced 2025-08-04 20:27:39 +02:00
add pipeline states and render passes logic
This commit is contained in:
141
src/cache.h
141
src/cache.h
@@ -16,8 +16,7 @@ struct ShaderCache {
|
||||
enum Effect { FX_NONE = 0, FX_UNDERWATER = 1, FX_ALPHA_TEST = 2 };
|
||||
|
||||
Shader *shaders[Core::passMAX][Shader::MAX][(FX_UNDERWATER | FX_ALPHA_TEST) + 1];
|
||||
PSO *pso[Core::passMAX][Shader::MAX][(FX_UNDERWATER | FX_ALPHA_TEST) + 1][bmMAX];
|
||||
|
||||
|
||||
ShaderCache() {
|
||||
memset(shaders, 0, sizeof(shaders));
|
||||
|
||||
@@ -47,82 +46,69 @@ struct ShaderCache {
|
||||
delete shaders[pass][type][fx];
|
||||
}
|
||||
|
||||
#define rsBase (RS_COLOR_WRITE | RS_DEPTH_TEST | RS_DEPTH_WRITE | RS_CULL_FRONT)
|
||||
#define rsBlend (RS_BLEND_ALPHA | RS_BLEND_ADD)
|
||||
#define rsFull (rsBase | rsBlend)
|
||||
#define rsShadow (RS_DEPTH_TEST | RS_DEPTH_WRITE | RS_CULL_BACK)
|
||||
|
||||
void prepareCompose(int fx) {
|
||||
compile(Core::passCompose, Shader::MIRROR, fx, rsBase);
|
||||
compile(Core::passCompose, Shader::MIRROR, fx);
|
||||
|
||||
compile(Core::passCompose, Shader::ROOM, fx, rsFull);
|
||||
compile(Core::passCompose, Shader::ROOM, fx, rsFull | RS_DISCARD);
|
||||
compile(Core::passCompose, Shader::ROOM, fx | FX_UNDERWATER, rsFull);
|
||||
compile(Core::passCompose, Shader::ROOM, fx | FX_UNDERWATER, rsFull | RS_DISCARD);
|
||||
compile(Core::passCompose, Shader::ROOM, fx);
|
||||
compile(Core::passCompose, Shader::ROOM, fx | FX_ALPHA_TEST);
|
||||
compile(Core::passCompose, Shader::ROOM, fx | FX_UNDERWATER);
|
||||
compile(Core::passCompose, Shader::ROOM, fx | FX_UNDERWATER | FX_ALPHA_TEST);
|
||||
|
||||
compile(Core::passCompose, Shader::ENTITY, fx, rsFull);
|
||||
compile(Core::passCompose, Shader::ENTITY, fx, rsFull | RS_DISCARD);
|
||||
compile(Core::passCompose, Shader::ENTITY, fx | FX_UNDERWATER, rsFull);
|
||||
compile(Core::passCompose, Shader::ENTITY, fx | FX_UNDERWATER, rsFull | RS_DISCARD);
|
||||
compile(Core::passCompose, Shader::ENTITY, fx);
|
||||
compile(Core::passCompose, Shader::ENTITY, fx | FX_ALPHA_TEST);
|
||||
compile(Core::passCompose, Shader::ENTITY, fx | FX_UNDERWATER);
|
||||
compile(Core::passCompose, Shader::ENTITY, fx | FX_UNDERWATER | FX_ALPHA_TEST);
|
||||
|
||||
compile(Core::passCompose, Shader::SPRITE, fx, rsFull | RS_DISCARD);
|
||||
compile(Core::passCompose, Shader::SPRITE, fx | FX_UNDERWATER, rsFull | RS_DISCARD);
|
||||
compile(Core::passCompose, Shader::SPRITE, fx | FX_ALPHA_TEST);
|
||||
compile(Core::passCompose, Shader::SPRITE, fx | FX_UNDERWATER | FX_ALPHA_TEST);
|
||||
|
||||
compile(Core::passCompose, Shader::FLASH, fx, rsFull | RS_BLEND_MULT); // spot shadow
|
||||
compile(Core::passCompose, Shader::FLASH, fx); // spot shadow
|
||||
}
|
||||
|
||||
void prepareAmbient(int fx) {
|
||||
compile(Core::passAmbient, Shader::ROOM, fx, rsFull);
|
||||
compile(Core::passAmbient, Shader::ROOM, fx, rsFull | RS_DISCARD);
|
||||
compile(Core::passAmbient, Shader::SPRITE, fx, rsFull | RS_DISCARD);
|
||||
compile(Core::passAmbient, Shader::ROOM, fx);
|
||||
compile(Core::passAmbient, Shader::ROOM, fx | FX_ALPHA_TEST);
|
||||
compile(Core::passAmbient, Shader::SPRITE, fx | FX_ALPHA_TEST);
|
||||
}
|
||||
|
||||
void prepareShadows(int fx) {
|
||||
compile(Core::passShadow, Shader::MIRROR, fx, rsShadow);
|
||||
compile(Core::passShadow, Shader::ENTITY, fx, rsShadow);
|
||||
compile(Core::passShadow, Shader::ENTITY, fx, rsShadow | RS_DISCARD);
|
||||
compile(Core::passShadow, Shader::MIRROR, fx);
|
||||
compile(Core::passShadow, Shader::ENTITY, fx);
|
||||
compile(Core::passShadow, Shader::ENTITY, fx | FX_ALPHA_TEST);
|
||||
}
|
||||
|
||||
void prepareSky(int fx) {
|
||||
compile(Core::passSky, Shader::DEFAULT, fx, rsBase);
|
||||
compile(Core::passSky, Shader::DEFAULT, fx);
|
||||
if (Core::support.tex3D) {
|
||||
compile(Core::passSky, Shader::SKY_CLOUDS, fx, rsBase);
|
||||
compile(Core::passSky, Shader::SKY_CLOUDS_AZURE, fx, rsBase);
|
||||
compile(Core::passSky, Shader::SKY_CLOUDS, fx);
|
||||
compile(Core::passSky, Shader::SKY_CLOUDS_AZURE, fx);
|
||||
}
|
||||
}
|
||||
|
||||
void prepareWater(int fx) {
|
||||
compile(Core::passWater, Shader::WATER_MASK, fx, RS_COLOR_WRITE_A | RS_DEPTH_TEST);
|
||||
compile(Core::passWater, Shader::WATER_SIMULATE, fx, RS_COLOR_WRITE);
|
||||
compile(Core::passWater, Shader::WATER_DROP, fx, RS_COLOR_WRITE);
|
||||
compile(Core::passWater, Shader::WATER_RAYS, fx, RS_COLOR_WRITE | RS_DEPTH_TEST);
|
||||
compile(Core::passWater, Shader::WATER_MASK, fx);
|
||||
compile(Core::passWater, Shader::WATER_SIMULATE, fx);
|
||||
compile(Core::passWater, Shader::WATER_DROP, fx);
|
||||
compile(Core::passWater, Shader::WATER_RAYS, fx);
|
||||
if (Core::support.derivatives) {
|
||||
compile(Core::passWater, Shader::WATER_CAUSTICS, fx, RS_COLOR_WRITE);
|
||||
compile(Core::passWater, Shader::WATER_CAUSTICS, fx);
|
||||
}
|
||||
compile(Core::passWater, Shader::WATER_COMPOSE, fx, RS_COLOR_WRITE | RS_DEPTH_TEST);
|
||||
compile(Core::passWater, Shader::WATER_COMPOSE, fx);
|
||||
}
|
||||
|
||||
void prepareFilter(int fx) {
|
||||
compile(Core::passFilter, Shader::FILTER_UPSCALE, fx, RS_COLOR_WRITE);
|
||||
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_ANAGLYPH, fx, RS_COLOR_WRITE);
|
||||
compile(Core::passFilter, Shader::FILTER_UPSCALE, fx);
|
||||
compile(Core::passFilter, Shader::FILTER_DOWNSAMPLE, fx);
|
||||
compile(Core::passFilter, Shader::FILTER_GRAYSCALE, fx);
|
||||
compile(Core::passFilter, Shader::FILTER_BLUR, fx);
|
||||
compile(Core::passFilter, Shader::FILTER_ANAGLYPH, fx);
|
||||
}
|
||||
|
||||
void prepareGUI(int fx) {
|
||||
compile(Core::passGUI, Shader::DEFAULT, fx, RS_COLOR_WRITE | RS_BLEND_ALPHA);
|
||||
compile(Core::passGUI, Shader::DEFAULT, fx);
|
||||
}
|
||||
|
||||
#undef rsBase
|
||||
#undef rsBlend
|
||||
#undef rsFull
|
||||
#undef rsShadow
|
||||
|
||||
Shader* compile(Core::Pass pass, Shader::Type type, int fx, uint32 rs) {
|
||||
if (rs & RS_DISCARD)
|
||||
fx |= FX_ALPHA_TEST;
|
||||
|
||||
Shader* compile(Core::Pass pass, Shader::Type type, int fx) {
|
||||
#ifndef FFP
|
||||
if (shaders[pass][type][fx])
|
||||
return shaders[pass][type][fx];
|
||||
@@ -196,7 +182,7 @@ struct ShaderCache {
|
||||
shader->setup();
|
||||
}
|
||||
|
||||
Core::setAlphaTest((fx & FX_ALPHA_TEST) != 0);
|
||||
//Core::setAlphaTest((fx & FX_ALPHA_TEST) != 0);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -259,7 +245,7 @@ struct AmbientCache {
|
||||
}
|
||||
|
||||
void renderAmbient(int room, int sector, vec4 *colors) {
|
||||
PROFILE_MARKER("PASS_AMBIENT");
|
||||
PROFILE_MARKER("ambient");
|
||||
|
||||
TR::Room &r = level->rooms[room];
|
||||
TR::Room::Sector &s = r.sectors[sector];
|
||||
@@ -274,8 +260,6 @@ struct AmbientCache {
|
||||
game->renderEnvironment(room, pos, textures, 4);
|
||||
|
||||
// second pass - downsample it
|
||||
Core::setDepthTest(false);
|
||||
|
||||
mat4 mProj, mView;
|
||||
mView.identity();
|
||||
mProj = GAPI::ortho(-1, +1, -1, +1, 0, 1);
|
||||
@@ -291,20 +275,22 @@ struct AmbientCache {
|
||||
for (int j = 0; j < 6; j++) {
|
||||
Texture *src = textures[j * 4 + i - 1];
|
||||
Texture *dst = textures[j * 4 + i];
|
||||
Core::setTarget(dst, NULL, RT_STORE_COLOR);
|
||||
Core::validateRenderState();
|
||||
|
||||
Core::beginRenderPass(RP_FILTER, RenderTarget(dst, 0, 0), RenderTarget(NULL, 0, 0));
|
||||
Core::setPipelineState(PS_FILTER_DOWNSAMPLE);
|
||||
|
||||
src->bind(sDiffuse);
|
||||
game->getMesh()->renderQuad();
|
||||
|
||||
Core::endRenderPass();
|
||||
}
|
||||
}
|
||||
|
||||
// get result color from 1x1 textures
|
||||
for (int j = 0; j < 6; j++) {
|
||||
Core::setTarget(textures[j * 4 + 3], NULL, RT_LOAD_COLOR);
|
||||
colors[j] = Core::copyPixel(0, 0);
|
||||
colors[j] = Core::copyPixel(textures[j * 4 + 3], 0, 0);
|
||||
}
|
||||
|
||||
Core::setDepthTest(true);
|
||||
Core::setClearColor(vec4(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
@@ -671,7 +657,7 @@ struct WaterCache {
|
||||
vec4 rPosScale[2] = { vec4(0.0f), vec4(1.0f) };
|
||||
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, s.x / item.data[0]->width, s.y / item.data[0]->height));
|
||||
|
||||
#if 0
|
||||
for (int i = 0; i < dropCount; i++) {
|
||||
Drop &drop = drops[i];
|
||||
|
||||
@@ -689,6 +675,7 @@ struct WaterCache {
|
||||
item.data[0]->unbind(sNormal);
|
||||
swap(item.data[0], item.data[1]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void step(Item &item) {
|
||||
@@ -700,7 +687,7 @@ struct WaterCache {
|
||||
Core::active.shader->setParam(uParam, vec4(0.995f, 1.0f, randf() * 0.5f, Core::params.x));
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f / item.data[0]->width, 1.0f / item.data[0]->height, s.x / item.data[0]->width, s.y / item.data[0]->height));
|
||||
Core::active.shader->setParam(uRoomSize, vec4(1.0f / item.mask->origWidth, 1.0f / item.mask->origHeight, float(item.mask->origWidth) / item.mask->width, float(item.mask->origHeight) / item.mask->height));
|
||||
|
||||
#if 0
|
||||
while (item.timer >= SIMULATE_TIMESTEP) {
|
||||
// water step
|
||||
Core::setTarget(item.data[1], NULL, RT_STORE_COLOR);
|
||||
@@ -734,6 +721,7 @@ struct WaterCache {
|
||||
item.data[0]->bind(sNormal);
|
||||
game->getMesh()->renderPlane();
|
||||
item.data[0]->unbind(sNormal);
|
||||
#endif
|
||||
}
|
||||
|
||||
void renderRays() {
|
||||
@@ -761,7 +749,7 @@ struct WaterCache {
|
||||
|
||||
Core::active.shader->setParam(uPosScale, rPosScale[0], 2);
|
||||
Core::active.shader->setParam(uParam, vec4(level->rooms[item.to].getOffset(), 0.35f));
|
||||
|
||||
#if 0
|
||||
Core::setBlendMode(bmAdd);
|
||||
Core::setCullMode(cmBack);
|
||||
Core::setDepthWrite(false);
|
||||
@@ -769,6 +757,7 @@ struct WaterCache {
|
||||
Core::setDepthWrite(true);
|
||||
Core::setCullMode(cmFront);
|
||||
Core::setBlendMode(bmNone);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
@@ -778,12 +767,12 @@ struct WaterCache {
|
||||
// mask underwater geometry by zero alpha
|
||||
game->setShader(Core::passWater, Shader::WATER_MASK);
|
||||
Core::active.shader->setParam(uTexParam, vec4(1.0f));
|
||||
|
||||
#if 0
|
||||
Core::setColorWrite(false, false, false, true);
|
||||
Core::setDepthWrite(false);
|
||||
Core::setCullMode(cmNone);
|
||||
Core::setBlendMode(bmNone);
|
||||
|
||||
#endif
|
||||
for (int i = 0; i < count; i++) {
|
||||
Item &item = items[i];
|
||||
if (!item.visible) continue;
|
||||
@@ -793,10 +782,11 @@ struct WaterCache {
|
||||
|
||||
game->getMesh()->renderQuad();
|
||||
}
|
||||
|
||||
#if 0
|
||||
Core::setColorWrite(true, true, true, true);
|
||||
Core::setDepthWrite(true);
|
||||
Core::setCullMode(cmFront);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -805,7 +795,6 @@ struct WaterCache {
|
||||
int h = Core::viewportDef.w;
|
||||
// get refraction texture
|
||||
if (!refract || w != refract->origWidth || h != refract->origHeight) {
|
||||
PROFILE_MARKER("WATER_REFRACT_INIT");
|
||||
delete refract;
|
||||
refract = new Texture(w, h, 1, FMT_RGBA, OPT_TARGET);
|
||||
#ifdef USE_SCREEN_TEX
|
||||
@@ -817,7 +806,7 @@ struct WaterCache {
|
||||
}
|
||||
|
||||
void copyScreenToRefraction() {
|
||||
PROFILE_MARKER("WATER_REFRACT_COPY");
|
||||
PROFILE_MARKER("water_copy_refraction");
|
||||
// get refraction texture
|
||||
int x, y;
|
||||
if (!screen) {
|
||||
@@ -826,7 +815,7 @@ struct WaterCache {
|
||||
} else {
|
||||
x = y = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (screen) {
|
||||
Core::setTarget(refract, NULL, RT_LOAD_DEPTH | RT_STORE_COLOR | RT_STORE_DEPTH);
|
||||
Core::validateRenderState();
|
||||
@@ -840,11 +829,13 @@ struct WaterCache {
|
||||
} else {
|
||||
Core::copyTarget(refract, 0, 0, x, y, Core::viewportDef.z, Core::viewportDef.w); // copy framebuffer into refraction texture
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void simulate() {
|
||||
PROFILE_MARKER("WATER_SIMULATE");
|
||||
PROFILE_MARKER("water_simulate");
|
||||
// simulate water
|
||||
#if 0
|
||||
Core::setDepthTest(false);
|
||||
Core::setBlendMode(bmNone);
|
||||
for (int i = 0; i < count; i++) {
|
||||
@@ -861,18 +852,19 @@ struct WaterCache {
|
||||
}
|
||||
}
|
||||
Core::setDepthTest(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void renderReflection() {
|
||||
if (!visible) return;
|
||||
PROFILE_MARKER("WATER_REFLECT");
|
||||
PROFILE_MARKER("water_reflection");
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
Item &item = items[i];
|
||||
if (item.visible && item.blank)
|
||||
item.init(game);
|
||||
}
|
||||
|
||||
#if 0
|
||||
// render mirror reflection
|
||||
Core::setTarget(reflect, NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR);
|
||||
Camera *camera = (Camera*)game->getCamera();
|
||||
@@ -928,11 +920,12 @@ struct WaterCache {
|
||||
|
||||
camera->reflectPlane = NULL;
|
||||
camera->setup(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void compose() {
|
||||
if (!visible) return;
|
||||
PROFILE_MARKER("WATER_COMPOSE");
|
||||
PROFILE_MARKER("water_compose");
|
||||
for (int i = 0; i < count; i++) {
|
||||
Item &item = items[i];
|
||||
if (!item.visible) continue;
|
||||
@@ -953,6 +946,7 @@ struct WaterCache {
|
||||
reflect->bind(sReflect);
|
||||
item.mask->bind(sMask);
|
||||
item.data[0]->bind(sNormal);
|
||||
#if 0
|
||||
Core::setCullMode(cmNone);
|
||||
Core::setBlendMode(bmAlpha);
|
||||
#ifdef WATER_USE_GRID
|
||||
@@ -966,6 +960,7 @@ struct WaterCache {
|
||||
#endif
|
||||
Core::setCullMode(cmFront);
|
||||
Core::setBlendMode(bmNone);
|
||||
#endif
|
||||
}
|
||||
dropCount = 0;
|
||||
}
|
||||
@@ -1010,14 +1005,14 @@ struct WaterCache {
|
||||
vertices[2].texCoord = short4(32767, 0, 0, 0);
|
||||
vertices[3].texCoord = short4( 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
Core::setDepthTest(false);
|
||||
Core::setBlendMode(bmNone);
|
||||
|
||||
game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices));
|
||||
|
||||
Core::setDepthTest(true);
|
||||
|
||||
#endif
|
||||
tex->unbind(sDiffuse);
|
||||
}
|
||||
|
||||
|
@@ -78,7 +78,7 @@ struct IGame {
|
||||
virtual void setupBinding() {}
|
||||
virtual void getVisibleRooms(RoomDesc *roomsList, int &roomsCount, int from, int to, const vec4 &viewPort, bool water, int count = 0) {}
|
||||
virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0, Core::Pass pass = Core::passAmbient) {}
|
||||
virtual void renderModelFull(int modelIndex, bool underwater, Basis *joints) {}
|
||||
virtual void renderModelFull(int modelIndex, Basis *joints) {}
|
||||
virtual void renderCompose(int roomIndex) {}
|
||||
virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) {}
|
||||
virtual void renderGame(bool showUI, bool invBG) {}
|
||||
@@ -1385,9 +1385,6 @@ struct Controller {
|
||||
}
|
||||
|
||||
void renderShadow(MeshBuilder *mesh) {
|
||||
if (Core::pass != Core::passCompose || level->isCutsceneLevel())
|
||||
return;
|
||||
|
||||
Box boxL = getBoundingBoxLocal();
|
||||
Box boxA = boxL * getMatrix();
|
||||
|
||||
@@ -1422,9 +1419,7 @@ struct Controller {
|
||||
float lum = 1.0f - alpha;
|
||||
Core::setMaterial(lum, lum, lum, alpha);
|
||||
|
||||
Core::setDepthWrite(false);
|
||||
mesh->renderShadowBlob();
|
||||
Core::setDepthWrite(true);
|
||||
}
|
||||
|
||||
void updateJoints() {
|
||||
|
392
src/core.h
392
src/core.h
@@ -78,6 +78,7 @@
|
||||
#elif __linux__
|
||||
#define _OS_LINUX 1
|
||||
#define _GAPI_GL 1
|
||||
//#define _GAPI_VULKAN 1
|
||||
#elif __APPLE__
|
||||
#define _GAPI_GL 1
|
||||
#include "TargetConditionals.h"
|
||||
@@ -217,16 +218,6 @@ struct KeySet {
|
||||
KeySet(InputKey key, JoyKey joy) : key(key), joy(joy) {}
|
||||
};
|
||||
|
||||
enum RenderTargetOp {
|
||||
RT_CLEAR_COLOR = 0x0001,
|
||||
RT_LOAD_COLOR = 0x0002,
|
||||
RT_STORE_COLOR = 0x0004,
|
||||
|
||||
RT_CLEAR_DEPTH = 0x0008,
|
||||
RT_LOAD_DEPTH = 0x0010,
|
||||
RT_STORE_DEPTH = 0x0020,
|
||||
};
|
||||
|
||||
namespace Core {
|
||||
|
||||
struct Mutex {
|
||||
@@ -425,28 +416,6 @@ namespace GAPI {
|
||||
struct Texture;
|
||||
}
|
||||
|
||||
enum RenderState {
|
||||
RS_TARGET = 1 << 0,
|
||||
RS_VIEWPORT = 1 << 1,
|
||||
RS_SCISSOR = 1 << 2,
|
||||
RS_DEPTH_TEST = 1 << 3,
|
||||
RS_DEPTH_WRITE = 1 << 4,
|
||||
RS_COLOR_WRITE_R = 1 << 5,
|
||||
RS_COLOR_WRITE_G = 1 << 6,
|
||||
RS_COLOR_WRITE_B = 1 << 7,
|
||||
RS_COLOR_WRITE_A = 1 << 8,
|
||||
RS_COLOR_WRITE = RS_COLOR_WRITE_R | RS_COLOR_WRITE_G | RS_COLOR_WRITE_B | RS_COLOR_WRITE_A,
|
||||
RS_CULL_BACK = 1 << 9,
|
||||
RS_CULL_FRONT = 1 << 10,
|
||||
RS_CULL = RS_CULL_BACK | RS_CULL_FRONT,
|
||||
RS_BLEND_ALPHA = 1 << 11,
|
||||
RS_BLEND_ADD = 1 << 12,
|
||||
RS_BLEND_MULT = 1 << 13,
|
||||
RS_BLEND_PREMULT = 1 << 14,
|
||||
RS_BLEND = RS_BLEND_ALPHA | RS_BLEND_ADD | RS_BLEND_MULT | RS_BLEND_PREMULT,
|
||||
RS_DISCARD = 1 << 15,
|
||||
};
|
||||
|
||||
// Texture image format
|
||||
enum TexFormat {
|
||||
FMT_LUMINANCE,
|
||||
@@ -460,7 +429,7 @@ enum TexFormat {
|
||||
FMT_MAX,
|
||||
};
|
||||
|
||||
// Texture options
|
||||
// Texture options // TODO rename to TO_
|
||||
enum TexOption {
|
||||
OPT_REPEAT = 0x0001,
|
||||
OPT_CUBEMAP = 0x0002,
|
||||
@@ -475,22 +444,13 @@ enum TexOption {
|
||||
OPT_VRAM_3DS = 0x0400,
|
||||
};
|
||||
|
||||
// Pipeline State Object
|
||||
struct PSO {
|
||||
void *data;
|
||||
void *shader;
|
||||
vec4 clearColor;
|
||||
TexFormat colorFormat;
|
||||
TexFormat depthFormat;
|
||||
uint32 renderState;
|
||||
};
|
||||
|
||||
#if !defined(FFP) && (defined(_OS_WIN) || defined(_OS_LINUX) || defined(_OS_MAC) || defined(_OS_WEB))
|
||||
typedef uint32 Index;
|
||||
#else
|
||||
typedef uint16 Index;
|
||||
#endif
|
||||
|
||||
// TODO move to mesh.h
|
||||
struct Edge {
|
||||
Index a, b;
|
||||
|
||||
@@ -606,6 +566,89 @@ const char *UniformName[uMAX] = { SHADER_UNIFORMS(DECL_STR) };
|
||||
enum CullMode { cmNone, cmBack, cmFront, cmMAX };
|
||||
enum BlendMode { bmNone, bmAlpha, bmAdd, bmMult, bmPremult, bmMAX };
|
||||
|
||||
enum RenderPassType {
|
||||
RP_MAIN,
|
||||
RP_SHADOW,
|
||||
RP_FILTER,
|
||||
RP_WATER_PROCESS,
|
||||
RP_WATER_CAUSTICS,
|
||||
RP_MAX
|
||||
};
|
||||
|
||||
enum PipelineStateType {
|
||||
// RP_SHADOW
|
||||
PS_ENTITY_SHADOW,
|
||||
PS_ENTITY_SHADOW_ALPHA,
|
||||
// RP_MAIN
|
||||
PS_GUI,
|
||||
PS_ROOM,
|
||||
PS_ROOM_ALPHA,
|
||||
PS_ROOM_ADD,
|
||||
PS_ROOM_UNDERWATER,
|
||||
PS_ROOM_UNDERWATER_ALPHA,
|
||||
PS_ROOM_UNDERWATER_ADD,
|
||||
PS_AMBIENT,
|
||||
PS_AMBIENT_ALPHA,
|
||||
PS_AMBIENT_ADD,
|
||||
PS_AMBIENT_UNDERWATER,
|
||||
PS_AMBIENT_UNDERWATER_ALPHA,
|
||||
PS_AMBIENT_UNDERWATER_ADD,
|
||||
PS_ENTITY,
|
||||
PS_ENTITY_ALPHA,
|
||||
PS_ENTITY_ADD,
|
||||
PS_ENTITY_UNDERWATER,
|
||||
PS_ENTITY_UNDERWATER_ALPHA,
|
||||
PS_ENTITY_UNDERWATER_ADD,
|
||||
PS_ENTITY_MIRROR,
|
||||
PS_FLASH,
|
||||
PS_BLOB,
|
||||
PS_SPRITE,
|
||||
PS_SPRITE_UNDERWATER,
|
||||
PS_SKY,
|
||||
PS_SKY_CLOUDS,
|
||||
PS_SKY_CLOUDS_AZURE,
|
||||
PS_WATER_COMPOSE,
|
||||
PS_WATER_MASK,
|
||||
PS_WATER_RAYS,
|
||||
// RP_WATER_PROCESS
|
||||
PS_WATER_DROP,
|
||||
PS_WATER_CALC,
|
||||
// RP_WATER_CAUSTICS
|
||||
PS_WATER_CAUSTICS,
|
||||
// RP_FILTER
|
||||
PS_FILTER_UPSCALE,
|
||||
PS_FILTER_DOWNSAMPLE,
|
||||
PS_FILTER_GRAYSCALE,
|
||||
PS_FILTER_BLUR,
|
||||
PS_FILTER_ANAGLYPH,
|
||||
|
||||
PS_MAX,
|
||||
};
|
||||
|
||||
enum RenderPassOpt {
|
||||
RO_COLOR_CLEAR = (1 << 0),
|
||||
RO_COLOR_LOAD = (1 << 1),
|
||||
RO_COLOR_STORE = (1 << 2),
|
||||
RO_DEPTH_CLEAR = (1 << 3),
|
||||
RO_DEPTH_LOAD = (1 << 4),
|
||||
RO_DEPTH_STORE = (1 << 5),
|
||||
};
|
||||
|
||||
enum PipelineStateOpt {
|
||||
PO_DEPTH_TEST = (1 << 0),
|
||||
PO_DEPTH_WRITE = (1 << 1),
|
||||
PO_COLOR_WRITE_R = (1 << 2),
|
||||
PO_COLOR_WRITE_G = (1 << 3),
|
||||
PO_COLOR_WRITE_B = (1 << 4),
|
||||
PO_COLOR_WRITE_A = (1 << 5),
|
||||
PO_COLOR_WRITE = PO_COLOR_WRITE_R | PO_COLOR_WRITE_G | PO_COLOR_WRITE_B | PO_COLOR_WRITE_A,
|
||||
PO_CULL_BACK = (1 << 6),
|
||||
PO_CULL_FRONT = (1 << 7),
|
||||
PO_BLEND_ALPHA = (1 << 8),
|
||||
PO_BLEND_ADD = (1 << 9),
|
||||
PO_BLEND_MULT = (1 << 10),
|
||||
};
|
||||
|
||||
namespace Core {
|
||||
float eye;
|
||||
Texture *eyeTex[2];
|
||||
@@ -635,7 +678,9 @@ namespace Core {
|
||||
int32 renderState;
|
||||
|
||||
struct Active {
|
||||
const PSO *pso;
|
||||
RenderPassType rp;
|
||||
PipelineStateType ps;
|
||||
|
||||
GAPI::Shader *shader;
|
||||
GAPI::Texture *textures[8];
|
||||
GAPI::Texture *target;
|
||||
@@ -725,8 +770,26 @@ namespace Core {
|
||||
#include "shader.h"
|
||||
#include "video.h"
|
||||
|
||||
struct RenderTarget {
|
||||
Texture *target;
|
||||
int face;
|
||||
int mip;
|
||||
|
||||
RenderTarget(Texture *target, int face = 0, int mip = 0) : target(target), face(face), mip(mip) {}
|
||||
};
|
||||
|
||||
namespace Core {
|
||||
|
||||
GAPI::RenderPass* renderPasses[RP_MAX];
|
||||
GAPI::PipelineState* pipelineStates[PS_MAX];
|
||||
|
||||
#define MAX_CACHED_TARGETS 32
|
||||
|
||||
struct CachedTarget {
|
||||
Texture *tex;
|
||||
bool acquired;
|
||||
} cachedTargets[MAX_CACHED_TARGETS];
|
||||
|
||||
static const char *version = __DATE__;
|
||||
static int defLang = 0;
|
||||
|
||||
@@ -744,26 +807,132 @@ namespace Core {
|
||||
delete stream;
|
||||
|
||||
perlinTex = new Texture(PERLIN_TEX_SIZE, PERLIN_TEX_SIZE, PERLIN_TEX_SIZE, FMT_LUMINANCE, OPT_REPEAT | OPT_VOLUME, perlinData);
|
||||
/*/
|
||||
uint8 *pdata = new uint8[SQR(PERLIN_TEX_SIZE) * 4];
|
||||
int offset = 0;
|
||||
for (int k = 0; k < PERLIN_TEX_SIZE; k++) {
|
||||
int j = 0;
|
||||
for (int i = 0; i < SQR(PERLIN_TEX_SIZE); i++) {
|
||||
pdata[j + 0] = pdata[j + 1] = pdata[j + 2] = perlinData[offset + i];
|
||||
pdata[j + 3] = 255;
|
||||
j += 4;
|
||||
}
|
||||
char buf[256];
|
||||
sprintf(buf, "noise/perlin_%03d", k);
|
||||
Texture::SaveBMP(buf, (char*)pdata, PERLIN_TEX_SIZE, PERLIN_TEX_SIZE);
|
||||
offset += PERLIN_TEX_SIZE * PERLIN_TEX_SIZE;
|
||||
}
|
||||
delete[] pdata;
|
||||
*/
|
||||
|
||||
delete[] perlinData;
|
||||
}
|
||||
|
||||
void initRenderPasses() {
|
||||
memset(renderPasses, 0, sizeof(renderPasses));
|
||||
|
||||
renderPasses[RP_MAIN] = new GAPI::RenderPass(FMT_RGBA, FMT_DEPTH, RO_COLOR_CLEAR | RO_COLOR_STORE | RO_DEPTH_CLEAR);
|
||||
renderPasses[RP_SHADOW] = new GAPI::RenderPass(FMT_MAX, FMT_SHADOW, RO_DEPTH_CLEAR | RO_DEPTH_STORE);
|
||||
renderPasses[RP_FILTER] = new GAPI::RenderPass(FMT_RGBA, FMT_MAX, RO_COLOR_STORE);
|
||||
renderPasses[RP_WATER_PROCESS] = new GAPI::RenderPass(FMT_RG_HALF, FMT_MAX, RO_COLOR_STORE);
|
||||
renderPasses[RP_WATER_CAUSTICS] = new GAPI::RenderPass(FMT_RGBA, FMT_MAX, RO_COLOR_CLEAR | RO_COLOR_STORE);
|
||||
}
|
||||
|
||||
void initPipelineStates() {
|
||||
memset(pipelineStates, 0, sizeof(pipelineStates));
|
||||
|
||||
Shader *gui;
|
||||
Shader *shadow, *shadow_a;
|
||||
Shader *room, *room_a, *room_u, *room_ua;
|
||||
Shader *ambient, *ambient_a, *ambient_u, *ambient_ua;
|
||||
Shader *entity, *entity_a, *entity_u, *entity_ua, *entity_mirror;
|
||||
Shader *flash, *blob;
|
||||
Shader *sprite, *sprite_u;
|
||||
Shader *sky, *sky_clouds, *sky_clouds_azure;
|
||||
Shader *water_compose, *water_mask, *water_rays, *water_drop, *water_calc, *water_caustics;
|
||||
Shader *filter_upscale, *filter_downsample, *filter_grayscale, *filter_blur, *filter_anaglyph;
|
||||
|
||||
pipelineStates[PS_WATER_RAYS] = new GAPI::PipelineState(renderPasses[RP_MAIN], gui,
|
||||
PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
|
||||
pipelineStates[PS_ENTITY_SHADOW] = new GAPI::PipelineState(renderPasses[RP_SHADOW], shadow,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_ENTITY_SHADOW_ALPHA] = new GAPI::PipelineState(renderPasses[RP_SHADOW], shadow_a,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_CULL_BACK);
|
||||
|
||||
pipelineStates[PS_ROOM] = new GAPI::PipelineState(renderPasses[RP_MAIN], room,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_ROOM_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], room_a,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
pipelineStates[PS_ROOM_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], room,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_ROOM_UNDERWATER] = new GAPI::PipelineState(renderPasses[RP_MAIN], room_u,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_ROOM_UNDERWATER_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], room_ua,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
pipelineStates[PS_ROOM_UNDERWATER_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], room_u,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_AMBIENT] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_AMBIENT_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient_a,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
pipelineStates[PS_AMBIENT_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_AMBIENT_UNDERWATER] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient_u,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_AMBIENT_UNDERWATER_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient_ua,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
pipelineStates[PS_AMBIENT_UNDERWATER_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], ambient_u,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_ENTITY] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_ENTITY_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_a,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
pipelineStates[PS_ENTITY_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_ENTITY_UNDERWATER] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_u,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_ENTITY_UNDERWATER_ALPHA] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_ua,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
pipelineStates[PS_ENTITY_UNDERWATER_ADD] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_u,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_ENTITY_MIRROR] = new GAPI::PipelineState(renderPasses[RP_MAIN], entity_mirror,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
|
||||
pipelineStates[PS_FLASH] = new GAPI::PipelineState(renderPasses[RP_MAIN], flash,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_BLOB] = new GAPI::PipelineState(renderPasses[RP_MAIN], blob,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_MULT);
|
||||
|
||||
pipelineStates[PS_SPRITE] = new GAPI::PipelineState(renderPasses[RP_MAIN], sprite,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
pipelineStates[PS_SPRITE_UNDERWATER] = new GAPI::PipelineState(renderPasses[RP_MAIN], sprite_u,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
|
||||
pipelineStates[PS_SKY] = new GAPI::PipelineState(renderPasses[RP_MAIN], sky,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_SKY_CLOUDS] = new GAPI::PipelineState(renderPasses[RP_MAIN], sky_clouds,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_SKY_CLOUDS_AZURE] = new GAPI::PipelineState(renderPasses[RP_MAIN], sky_clouds_azure,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
|
||||
pipelineStates[PS_WATER_COMPOSE] = new GAPI::PipelineState(renderPasses[RP_MAIN], water_compose,
|
||||
PO_DEPTH_TEST | PO_DEPTH_WRITE | PO_COLOR_WRITE);
|
||||
pipelineStates[PS_WATER_MASK] = new GAPI::PipelineState(renderPasses[RP_MAIN], water_mask,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE_A);
|
||||
pipelineStates[PS_WATER_RAYS] = new GAPI::PipelineState(renderPasses[RP_MAIN], water_mask,
|
||||
PO_DEPTH_TEST | PO_COLOR_WRITE | PO_CULL_FRONT | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_WATER_DROP] = new GAPI::PipelineState(renderPasses[RP_WATER_PROCESS], water_drop,
|
||||
PO_COLOR_WRITE_R | PO_COLOR_WRITE_G | PO_CULL_BACK);
|
||||
pipelineStates[PS_WATER_CALC] = new GAPI::PipelineState(renderPasses[RP_WATER_PROCESS], water_calc,
|
||||
PO_COLOR_WRITE_R | PO_COLOR_WRITE_G | PO_CULL_BACK);
|
||||
|
||||
pipelineStates[PS_WATER_CAUSTICS] = new GAPI::PipelineState(renderPasses[RP_WATER_CAUSTICS], water_caustics,
|
||||
PO_COLOR_WRITE | PO_BLEND_ADD);
|
||||
|
||||
pipelineStates[PS_FILTER_UPSCALE] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_upscale,
|
||||
PO_COLOR_WRITE | PO_CULL_BACK | PO_BLEND_ALPHA);
|
||||
pipelineStates[PS_FILTER_DOWNSAMPLE] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_downsample,
|
||||
PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_FILTER_GRAYSCALE] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_grayscale,
|
||||
PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_FILTER_BLUR] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_blur,
|
||||
PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
pipelineStates[PS_FILTER_ANAGLYPH] = new GAPI::PipelineState(renderPasses[RP_FILTER], filter_anaglyph,
|
||||
PO_COLOR_WRITE | PO_CULL_BACK);
|
||||
}
|
||||
|
||||
void init() {
|
||||
LOG("OpenLara (%s)\n", version);
|
||||
|
||||
@@ -788,6 +957,9 @@ namespace Core {
|
||||
|
||||
GAPI::init();
|
||||
|
||||
initRenderPasses();
|
||||
initPipelineStates();
|
||||
|
||||
#ifdef _OS_3DS
|
||||
Core::eyeTex[0] = new Texture(Core::width, Core::height, 1, TexFormat::FMT_RGB16, OPT_TARGET | OPT_PROXY);
|
||||
Core::eyeTex[1] = new Texture(Core::width, Core::height, 1, TexFormat::FMT_RGB16, OPT_TARGET | OPT_PROXY);
|
||||
@@ -999,6 +1171,38 @@ namespace Core {
|
||||
Sound::deinit();
|
||||
}
|
||||
|
||||
Texture* acquireTarget(int width, int height, TexFormat fmt) {
|
||||
for (int i = 0; i < MAX_CACHED_TARGETS; i++) {
|
||||
CachedTarget &ct = cachedTargets[i];
|
||||
|
||||
if (ct.tex == NULL) {
|
||||
ct.acquired = true;
|
||||
ct.tex = new Texture(width, height, 1, fmt, OPT_TARGET | OPT_NEAREST);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!ct.acquired && ct.tex->origWidth == width && ct.tex->origHeight == height && ct.tex->fmt == fmt) {
|
||||
ct.acquired = true;
|
||||
return ct.tex;
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT(false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void releaseTarget(Texture *target) {
|
||||
for (int i = 0; i < MAX_CACHED_TARGETS; i++) {
|
||||
CachedTarget &ct = cachedTargets[i];
|
||||
if (ct.tex == target) {
|
||||
ASSERT(ct.acquired);
|
||||
ct.acquired = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
ASSERT(false);
|
||||
}
|
||||
|
||||
void setVSync(bool enable) {
|
||||
GAPI::setVSync((Core::settings.detail.vsync = enable));
|
||||
}
|
||||
@@ -1018,6 +1222,27 @@ namespace Core {
|
||||
return true;
|
||||
}
|
||||
|
||||
void beginRenderPass(RenderPassType rp, const RenderTarget &color, const RenderTarget &depth) {
|
||||
active.rp = rp;
|
||||
|
||||
ASSERT(renderPasses[active.rp]);
|
||||
renderPasses[active.rp]->begin(color.target, color.face, color.mip, depth.target);
|
||||
}
|
||||
|
||||
void endRenderPass() {
|
||||
ASSERT(active.rp < RP_MAX);
|
||||
ASSERT(renderPasses[active.rp]);
|
||||
renderPasses[active.rp]->end();
|
||||
active.rp = RP_MAX;
|
||||
}
|
||||
|
||||
void setPipelineState(PipelineStateType ps) {
|
||||
active.ps = ps;
|
||||
|
||||
ASSERT(pipelineStates[ps]);
|
||||
pipelineStates[ps]->bind();
|
||||
}
|
||||
/*
|
||||
void validateRenderState() {
|
||||
int32 mask = renderState ^ active.renderState;
|
||||
if (!mask) return;
|
||||
@@ -1086,14 +1311,14 @@ namespace Core {
|
||||
|
||||
active.renderState = renderState;
|
||||
}
|
||||
|
||||
*/
|
||||
void setClearColor(const vec4 &color) {
|
||||
GAPI::setClearColor(color);
|
||||
}
|
||||
|
||||
void setViewport(const short4 &v) {
|
||||
viewport = v;
|
||||
renderState |= RS_VIEWPORT;
|
||||
GAPI::setViewport(v);
|
||||
}
|
||||
|
||||
void setViewport(int x, int y, int width, int height) {
|
||||
@@ -1102,9 +1327,9 @@ namespace Core {
|
||||
|
||||
void setScissor(const short4 &s) {
|
||||
scissor = s;
|
||||
renderState |= RS_SCISSOR;
|
||||
GAPI::setScissor(s);
|
||||
}
|
||||
|
||||
/*
|
||||
void setCullMode(CullMode mode) {
|
||||
renderState &= ~RS_CULL;
|
||||
switch (mode) {
|
||||
@@ -1172,7 +1397,7 @@ namespace Core {
|
||||
reqTarget.face = face;
|
||||
renderState |= RS_TARGET;
|
||||
}
|
||||
|
||||
*/
|
||||
void setBasis(Basis *basis, int count) {
|
||||
Core::active.basis = basis;
|
||||
Core::active.basisCount = count;
|
||||
@@ -1218,43 +1443,48 @@ namespace Core {
|
||||
}
|
||||
|
||||
void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {
|
||||
validateRenderState();
|
||||
//validateRenderState();
|
||||
GAPI::copyTarget(dst, xOffset, yOffset, x, y, width, height);
|
||||
}
|
||||
|
||||
vec4 copyPixel(int x, int y) { // GPU sync!
|
||||
validateRenderState();
|
||||
return GAPI::copyPixel(x, y);
|
||||
vec4 copyPixel(Texture *texture, int x, int y) { // GPU sync!
|
||||
//validateRenderState();
|
||||
return GAPI::copyPixel(texture, x, y);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
}
|
||||
|
||||
bool beginFrame() {
|
||||
Core::stats.start();
|
||||
if (!GAPI::beginFrame()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GAPI::resetState();
|
||||
|
||||
memset(&active, 0, sizeof(active));
|
||||
renderState = 0;
|
||||
|
||||
active.rp = RP_MAX;
|
||||
active.ps = PS_MAX;
|
||||
|
||||
setViewport(Core::x, Core::y, Core::width, Core::height);
|
||||
viewportDef = viewport;
|
||||
scissor = viewport;
|
||||
|
||||
/*
|
||||
setCullMode(cmFront);
|
||||
setBlendMode(bmAlpha);
|
||||
setDepthTest(true);
|
||||
setDepthWrite(true);
|
||||
setColorWrite(true, true, true, true);
|
||||
validateRenderState();
|
||||
}
|
||||
|
||||
bool beginFrame() {
|
||||
Core::stats.start();
|
||||
return GAPI::beginFrame();
|
||||
*/
|
||||
return true;
|
||||
}
|
||||
|
||||
void endFrame() {
|
||||
if (active.target != defaultTarget) {
|
||||
GAPI::setTarget(NULL, NULL, 0);
|
||||
validateRenderState();
|
||||
}
|
||||
ASSERT(active.rp == RP_MAX);
|
||||
GAPI::endFrame();
|
||||
Core::stats.stop();
|
||||
}
|
||||
@@ -1268,7 +1498,7 @@ namespace Core {
|
||||
}
|
||||
|
||||
void DIP(GAPI::Mesh *mesh, const MeshRange &range) {
|
||||
validateRenderState();
|
||||
//validateRenderState();
|
||||
|
||||
mesh->bind(range);
|
||||
GAPI::DIP(mesh, range);
|
||||
|
@@ -309,7 +309,6 @@ namespace Game {
|
||||
|
||||
bool frameBegin() {
|
||||
if (Core::settings.version == SETTINGS_READING) return false;
|
||||
Core::reset();
|
||||
if (Core::beginFrame()) {
|
||||
level->renderPrepare();
|
||||
return true;
|
||||
|
124
src/gapi/gl.h
124
src/gapi/gl.h
@@ -493,6 +493,21 @@ namespace GAPI {
|
||||
char GLSL_HEADER_VERT[512];
|
||||
char GLSL_HEADER_FRAG[512];
|
||||
|
||||
GLuint FBO, defaultFBO;
|
||||
struct RenderTargetCacheItem {
|
||||
GLuint ID;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
Array<RenderTargetCacheItem> rtCache[2];
|
||||
|
||||
uint32 m_alphaTest;
|
||||
uint32 m_depthTest;
|
||||
uint32 m_depthWrite;
|
||||
uint32 m_colorMask;
|
||||
uint32 m_cullMode;
|
||||
uint32 m_blendMode;
|
||||
|
||||
// Shader
|
||||
#ifndef FFP
|
||||
const char SHADER_COMPOSE[] =
|
||||
@@ -550,7 +565,16 @@ namespace GAPI {
|
||||
#ifdef FFP
|
||||
void init(Core::Pass pass, int type, int *def, int defCount) {}
|
||||
void deinit() {}
|
||||
void bind() {}
|
||||
void bind() {
|
||||
if (alphaTest != m_alphaTest) {
|
||||
if (opt & PO_ALPHA_TEST) {
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
} else {
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
}
|
||||
m_alphaTest = alphaTest;
|
||||
}
|
||||
}
|
||||
void validate() {}
|
||||
void setParam(UniformType uType, const vec4 &value, int count = 1) {}
|
||||
void setParam(UniformType uType, const mat4 &value, int count = 1) {}
|
||||
@@ -1131,13 +1155,92 @@ namespace GAPI {
|
||||
};
|
||||
|
||||
|
||||
GLuint FBO, defaultFBO;
|
||||
struct RenderTargetCacheItem {
|
||||
GLuint ID;
|
||||
int width;
|
||||
int height;
|
||||
// RenderPass
|
||||
struct RenderPass {
|
||||
TexFormat colorFmt;
|
||||
TexFormat depthFmt;
|
||||
uint32 opt;
|
||||
|
||||
RenderPass(TexFormat colorFmt, TexFormat depthFmt, uint32 opt) : colorFmt(colorFmt), depthFmt(depthFmt), opt(opt) {}
|
||||
|
||||
void begin(Texture *color, int face, int mip, Texture *depth) {
|
||||
//setRenderTarget
|
||||
}
|
||||
|
||||
void end() {}
|
||||
};
|
||||
|
||||
|
||||
// PipelineState
|
||||
struct PipelineState {
|
||||
RenderPass *renderPass;
|
||||
Shader *shader;
|
||||
uint32 opt;
|
||||
|
||||
PipelineState(RenderPass *renderPass, Shader *shader, uint32 opt) : renderPass(renderPass), shader(shader), opt(opt) {}
|
||||
|
||||
void bind() {
|
||||
shader->bind();
|
||||
|
||||
uint32 depthTest = opt & PO_DEPTH_TEST;
|
||||
if (depthTest != m_depthTest) {
|
||||
if (depthTest) {
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
} else {
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
m_depthTest = depthTest;
|
||||
}
|
||||
|
||||
uint32 depthWrite = opt & PO_DEPTH_WRITE;
|
||||
if (depthWrite != m_depthWrite) {
|
||||
glDepthMask(depthWrite != 0);
|
||||
m_depthWrite = depthWrite;
|
||||
}
|
||||
|
||||
uint32 colorMask = opt & (PO_COLOR_WRITE_R | PO_COLOR_WRITE_G | PO_COLOR_WRITE_B | PO_COLOR_WRITE_A);
|
||||
if (colorMask != m_colorMask) {
|
||||
glColorMask((opt & PO_COLOR_WRITE_R),
|
||||
(opt & PO_COLOR_WRITE_G),
|
||||
(opt & PO_COLOR_WRITE_B),
|
||||
(opt & PO_COLOR_WRITE_A));
|
||||
m_colorMask = colorMask;
|
||||
}
|
||||
|
||||
uint32 cullMode = opt & (PO_CULL_BACK | PO_CULL_FRONT);
|
||||
if (cullMode != m_cullMode) {
|
||||
if (opt & PO_CULL_BACK) {
|
||||
glCullFace(GL_BACK);
|
||||
} else if (opt & PO_CULL_FRONT) {
|
||||
glCullFace(GL_FRONT);
|
||||
} else {
|
||||
glDisable(GL_CULL_FACE);
|
||||
}
|
||||
if (!m_cullMode) {
|
||||
glEnable(GL_CULL_FACE);
|
||||
}
|
||||
m_cullMode = cullMode;
|
||||
}
|
||||
|
||||
uint32 blendMode = opt & (PO_BLEND_ALPHA | PO_BLEND_ADD | PO_BLEND_MULT);
|
||||
if (blendMode != m_blendMode) {
|
||||
if (opt & PO_BLEND_ALPHA) {
|
||||
glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
|
||||
} else if (opt & PO_BLEND_ADD) {
|
||||
glBlendFunc(GL_ONE, GL_ONE);
|
||||
} else if (opt & PO_BLEND_MULT) {
|
||||
glBlendFunc(GL_DST_COLOR, GL_ZERO);
|
||||
} else {
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
if (!m_blendMode) {
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
m_blendMode = blendMode;
|
||||
}
|
||||
}
|
||||
};
|
||||
Array<RenderTargetCacheItem> rtCache[2];
|
||||
|
||||
bool extSupport(const char *str, const char *ext) {
|
||||
if (!str) return false;
|
||||
@@ -1594,7 +1697,7 @@ namespace GAPI {
|
||||
void setScissor(const short4 &s) {
|
||||
glScissor(s.x, s.y, s.z, s.w);
|
||||
}
|
||||
|
||||
/*
|
||||
void setDepthTest(bool enable) {
|
||||
if (enable)
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
@@ -1641,7 +1744,7 @@ namespace GAPI {
|
||||
}
|
||||
glEnable(GL_BLEND);
|
||||
}
|
||||
|
||||
*/
|
||||
void setViewProj(const mat4 &mView, const mat4 &mProj) {
|
||||
#ifdef FFP
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
@@ -1710,7 +1813,8 @@ namespace GAPI {
|
||||
glDrawElements(GL_TRIANGLES, range.iCount, sizeof(Index) == 2 ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT, mesh->iBuffer + range.iStart);
|
||||
}
|
||||
|
||||
vec4 copyPixel(int x, int y) {
|
||||
vec4 copyPixel(Texture *texture, int x, int y) {
|
||||
// TODO setTarget
|
||||
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);
|
||||
|
445
src/gapi/vk.h
445
src/gapi/vk.h
@@ -1,6 +1,449 @@
|
||||
#ifndef H_GAPI_VK
|
||||
#define H_GAPI_VK
|
||||
|
||||
// TODO
|
||||
#include "core.h"
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#if defined(_DEBUG) || defined(PROFILE)
|
||||
struct Marker {
|
||||
Marker(const char *title) {
|
||||
//
|
||||
}
|
||||
|
||||
~Marker() {
|
||||
//
|
||||
}
|
||||
|
||||
static void setLabel(void *object, const char *label) {
|
||||
// TODO: use Windows 10 SDK
|
||||
}
|
||||
};
|
||||
|
||||
#define PROFILE_MARKER(title) Marker marker##__LINE__(title)
|
||||
#define PROFILE_LABEL(id, child, label) Marker::setLabel(child, label)
|
||||
#define PROFILE_TIMING(time)
|
||||
#else
|
||||
#define PROFILE_MARKER(title)
|
||||
#define PROFILE_LABEL(id, child, label)
|
||||
#define PROFILE_TIMING(time)
|
||||
#endif
|
||||
|
||||
#define VK_INIT(s) memset(&s, 0, sizeof(s))
|
||||
#define VK_INIT_STRUCT(s,t) VK_INIT(s); s.sType = t
|
||||
#define VK_CHECK(x) { VkResult r = (x); if (r != VK_SUCCESS) { LOG("! %s = %d\n", #x, (int)r); ASSERT(r != VK_SUCCESS); } }
|
||||
|
||||
namespace GAPI {
|
||||
using namespace Core;
|
||||
|
||||
typedef ::Vertex Vertex;
|
||||
|
||||
enum {
|
||||
smpDefault,
|
||||
smpPoint,
|
||||
smpPointWrap,
|
||||
smpLinear,
|
||||
smpLinearWrap,
|
||||
smpCmp,
|
||||
smpMAX
|
||||
};
|
||||
|
||||
VkDevice device;
|
||||
VkInstance instance;
|
||||
|
||||
CullMode cullMode;
|
||||
BlendMode blendMode;
|
||||
vec4 clearColor;
|
||||
VkSampler samplers[smpMAX];
|
||||
|
||||
// Shader
|
||||
//#include "shaders/vulkan/shaders.h"
|
||||
|
||||
static const int bindings[uMAX] = {
|
||||
0, // uParam
|
||||
1, // uTexParam
|
||||
2, // uViewProj
|
||||
6, // uBasis
|
||||
70, // uLightProj
|
||||
74, // uMaterial
|
||||
75, // uAmbient
|
||||
81, // uFogParams
|
||||
82, // uViewPos
|
||||
83, // uLightPos
|
||||
87, // uLightColor
|
||||
91, // uRoomSize
|
||||
92, // uPosScale
|
||||
98, // uContacts
|
||||
};
|
||||
|
||||
struct Shader {
|
||||
VkShaderModule VS;
|
||||
VkShaderModule PS;
|
||||
|
||||
Shader() : VS(VK_NULL_HANDLE), PS(VK_NULL_HANDLE) {}
|
||||
|
||||
void init(Core::Pass pass, int type, int *def, int defCount) {
|
||||
//
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
vkDestroyShaderModule(device, VS, NULL);
|
||||
vkDestroyShaderModule(device, PS, NULL);
|
||||
}
|
||||
|
||||
void bind() {
|
||||
//
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, float *value, int count) {
|
||||
//
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const vec4 &value, int count = 1) {
|
||||
setParam(uType, (float*)&value, count);
|
||||
}
|
||||
|
||||
void setParam(UniformType uType, const mat4 &value, int count = 1) {
|
||||
setParam(uType, (float*)&value, count * 4);
|
||||
}
|
||||
};
|
||||
|
||||
// Texture
|
||||
struct Texture {
|
||||
VkImage image;
|
||||
VkImageView imageView;
|
||||
|
||||
int width, height, depth, origWidth, origHeight, origDepth;
|
||||
TexFormat fmt;
|
||||
uint32 opt;
|
||||
|
||||
Texture(int width, int height, int depth, uint32 opt) : image(VK_NULL_HANDLE), imageView(VK_NULL_HANDLE), width(width), height(height), depth(depth), origWidth(width), origHeight(height), origDepth(depth), fmt(FMT_RGBA), opt(opt) {
|
||||
//
|
||||
}
|
||||
|
||||
void init(void *data) {
|
||||
ASSERT((opt & OPT_PROXY) == 0);
|
||||
|
||||
bool mipmaps = (opt & OPT_MIPMAPS) != 0;
|
||||
bool isDepth = fmt == FMT_DEPTH || fmt == FMT_SHADOW;
|
||||
bool isCube = (opt & OPT_CUBEMAP) != 0;
|
||||
bool isVolume = (opt & OPT_VOLUME) != 0;
|
||||
bool isTarget = (opt & OPT_TARGET) != 0;
|
||||
bool isDynamic = (opt & OPT_DYNAMIC) != 0;
|
||||
|
||||
static const struct FormatDesc {
|
||||
int bpp;
|
||||
VkFormat format;
|
||||
} formats[FMT_MAX] = {
|
||||
{ 8, VK_FORMAT_R8_UNORM },
|
||||
{ 32, VK_FORMAT_R8G8B8A8_UNORM },
|
||||
{ 16, VK_FORMAT_B5G6R5_UNORM_PACK16 },
|
||||
{ 16, VK_FORMAT_B5G5R5A1_UNORM_PACK16 },
|
||||
{ 64, VK_FORMAT_R32G32_SFLOAT },
|
||||
{ 32, VK_FORMAT_R16G16_SFLOAT },
|
||||
{ 16, VK_FORMAT_R16_UNORM },
|
||||
{ 16, VK_FORMAT_R16_UNORM },
|
||||
};
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
vkDestroyImage(device, image, NULL);
|
||||
vkDestroyImageView(device, imageView, NULL);
|
||||
}
|
||||
|
||||
void generateMipMap() {
|
||||
//
|
||||
}
|
||||
|
||||
void update(void *data) {
|
||||
//
|
||||
}
|
||||
|
||||
void bind(int sampler) {
|
||||
if (opt & OPT_PROXY) return;
|
||||
//
|
||||
}
|
||||
|
||||
void unbind(int sampler) {
|
||||
//
|
||||
}
|
||||
|
||||
void setFilterQuality(int value) {
|
||||
//
|
||||
}
|
||||
};
|
||||
|
||||
// Mesh
|
||||
struct Mesh {
|
||||
VkBuffer IB;
|
||||
VkBuffer VB;
|
||||
|
||||
int iCount;
|
||||
int vCount;
|
||||
bool dynamic;
|
||||
|
||||
Mesh(bool dynamic) : IB(VK_NULL_HANDLE), VB(VK_NULL_HANDLE), 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));
|
||||
//
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
vkDestroyBuffer(device, IB, NULL);
|
||||
vkDestroyBuffer(device, VB, NULL);
|
||||
}
|
||||
|
||||
void update(Index *indices, int iCount, ::Vertex *vertices, int vCount) {
|
||||
ASSERT(sizeof(GAPI::Vertex) == sizeof(::Vertex));
|
||||
|
||||
if (indices && iCount) {
|
||||
//
|
||||
}
|
||||
|
||||
if (vertices && vCount) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
void bind(const MeshRange &range) const {
|
||||
//
|
||||
}
|
||||
|
||||
void initNextRange(MeshRange &range, int &aIndex) const {
|
||||
range.aIndex = -1;
|
||||
}
|
||||
};
|
||||
|
||||
// GLuint FBO, defaultFBO;
|
||||
struct RenderTargetCache {
|
||||
int count;
|
||||
struct Item {
|
||||
int width;
|
||||
int height;
|
||||
} items[MAX_RENDER_BUFFERS];
|
||||
} rtCache;
|
||||
|
||||
void deinitSamplers() {
|
||||
for (int i = 0; i < COUNT(samplers); i++) {
|
||||
//vkDestroySampler(device, samplers[i], NULL);
|
||||
}
|
||||
}
|
||||
|
||||
VkSampler initSampler(bool filter, bool aniso, bool wrap, bool cmp) {
|
||||
VkSamplerCreateInfo createInfo;
|
||||
VK_INIT_STRUCT(createInfo, VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO);
|
||||
|
||||
if (aniso && (Core::support.maxAniso > 0)) {
|
||||
createInfo.maxAnisotropy = min(int(Core::support.maxAniso), 8);
|
||||
} else {
|
||||
createInfo.maxAnisotropy = 1;
|
||||
}
|
||||
|
||||
createInfo.anisotropyEnable = (createInfo.maxAnisotropy > 1) ? VK_TRUE : VK_FALSE;
|
||||
|
||||
if (filter) {
|
||||
createInfo.minFilter = VK_FILTER_LINEAR;
|
||||
createInfo.magFilter = VK_FILTER_LINEAR;
|
||||
createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
} else {
|
||||
createInfo.minFilter = VK_FILTER_LINEAR;
|
||||
createInfo.magFilter = VK_FILTER_LINEAR;
|
||||
createInfo.mipmapMode = VK_SAMPLER_MIPMAP_MODE_LINEAR;
|
||||
}
|
||||
|
||||
if (cmp) {
|
||||
createInfo.compareEnable = VK_TRUE;
|
||||
createInfo.compareOp = VK_COMPARE_OP_LESS;
|
||||
createInfo.borderColor = VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE;
|
||||
}
|
||||
|
||||
createInfo.addressModeU =
|
||||
createInfo.addressModeV =
|
||||
createInfo.addressModeW = cmp ? VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER : (wrap ? VK_SAMPLER_ADDRESS_MODE_REPEAT : VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE);
|
||||
createInfo.minLod = 0.0f;
|
||||
createInfo.maxLod = 0.0f;
|
||||
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
//VK_CHECK(vkCreateSampler(device, &createInfo, NULL, &sampler));
|
||||
return sampler;
|
||||
}
|
||||
|
||||
void initSamplers() {
|
||||
deinitSamplers();
|
||||
samplers[smpDefault] = initSampler(true, true, false, false); // TODO settings dependent
|
||||
samplers[smpPoint] = initSampler(false, false, false, false);
|
||||
samplers[smpPointWrap] = initSampler(false, false, true, false);
|
||||
samplers[smpLinear] = initSampler(true, false, false, false);
|
||||
samplers[smpLinearWrap] = initSampler(true, false, true, false);
|
||||
samplers[smpCmp] = initSampler(true, false, false, true);
|
||||
}
|
||||
|
||||
void init() {
|
||||
memset(&rtCache, 0, sizeof(rtCache));
|
||||
memset(samplers, 0, sizeof(samplers));
|
||||
|
||||
/* TODO
|
||||
D3DADAPTER_IDENTIFIER9 adapterInfo;
|
||||
D3D->GetAdapterIdentifier(D3DADAPTER_DEFAULT, 0, &adapterInfo);
|
||||
LOG("Vendor : %s\n", adapterInfo.Description);
|
||||
LOG("Renderer : Direct3D 9.0c\n");
|
||||
*/
|
||||
|
||||
support.maxAniso = 8;
|
||||
support.maxVectors = 16;
|
||||
support.shaderBinary = true;
|
||||
support.VAO = false; // SHADOW_COLOR
|
||||
support.depthTexture = true;
|
||||
support.shadowSampler = true;
|
||||
support.discardFrame = false;
|
||||
support.texNPOT = true;
|
||||
support.texRG = true;
|
||||
support.texBorder = true;
|
||||
support.colorFloat = true;
|
||||
support.colorHalf = true;
|
||||
support.texFloatLinear = true;
|
||||
support.texFloat = true;
|
||||
support.texHalfLinear = true;
|
||||
support.texHalf = true;
|
||||
support.tex3D = true;
|
||||
|
||||
// init samplers
|
||||
memset(samplers, 0, sizeof(samplers));
|
||||
initSamplers();
|
||||
}
|
||||
|
||||
void resetDevice() {
|
||||
rtCache.count = 0;
|
||||
}
|
||||
|
||||
void deinit() {
|
||||
resetDevice();
|
||||
|
||||
deinitSamplers();
|
||||
}
|
||||
|
||||
inline mat4::ProjRange getProjRange() {
|
||||
return mat4::PROJ_ZERO_POS;
|
||||
}
|
||||
|
||||
mat4 ortho(float l, float r, float b, float t, float znear, float zfar) {
|
||||
mat4 m;
|
||||
m.ortho(getProjRange(), l, r, b, t, znear, zfar);
|
||||
return m;
|
||||
}
|
||||
|
||||
mat4 perspective(float fov, float aspect, float znear, float zfar, float eye) {
|
||||
mat4 m;
|
||||
m.perspective(getProjRange(), fov, aspect, znear, zfar, eye);
|
||||
return m;
|
||||
}
|
||||
|
||||
bool beginFrame() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void endFrame() {
|
||||
//
|
||||
}
|
||||
|
||||
void resetState() {
|
||||
//
|
||||
}
|
||||
|
||||
void cacheRenderTarget(VkImageView **RTV, VkImageView **DSV, int width, int height) {
|
||||
ASSERT((RTV != NULL) ^ (DSV != NULL));
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i < rtCache.count; i++)
|
||||
if (rtCache.items[i].width == width && rtCache.items[i].height == height) {
|
||||
index = i;
|
||||
break;
|
||||
}
|
||||
|
||||
ASSERT(rtCache.count < MAX_RENDER_BUFFERS);
|
||||
|
||||
if (index == -1) {
|
||||
index = rtCache.count++;
|
||||
rtCache.items[index].width = width;
|
||||
rtCache.items[index].height = height;
|
||||
}
|
||||
|
||||
//
|
||||
}
|
||||
|
||||
void bindTarget(Texture *target, int face) {
|
||||
//
|
||||
}
|
||||
|
||||
void discardTarget(bool color, bool depth) {}
|
||||
|
||||
void copyTarget(Texture *dst, int xOffset, int yOffset, int x, int y, int width, int height) {
|
||||
//
|
||||
}
|
||||
|
||||
void setVSync(bool enable) {}
|
||||
void waitVBlank() {}
|
||||
|
||||
void clear(bool color, bool depth) {
|
||||
//
|
||||
}
|
||||
|
||||
void setClearColor(const vec4 &color) {
|
||||
clearColor = color;
|
||||
}
|
||||
|
||||
void setViewport(const short4 &v) {
|
||||
//
|
||||
}
|
||||
|
||||
void setScissor(const short4 &s) {
|
||||
//
|
||||
}
|
||||
|
||||
void setDepthTest(bool enable) {
|
||||
//
|
||||
}
|
||||
|
||||
void setDepthWrite(bool enable) {
|
||||
//
|
||||
}
|
||||
|
||||
void setColorWrite(bool r, bool g, bool b, bool a) {
|
||||
//
|
||||
}
|
||||
|
||||
void setAlphaTest(bool enable) {}
|
||||
|
||||
void setCullMode(int rsMask) {
|
||||
//
|
||||
}
|
||||
|
||||
void setBlendMode(int rsMask) {
|
||||
//
|
||||
}
|
||||
|
||||
void setViewProj(const mat4 &mView, const mat4 &mProj) {}
|
||||
|
||||
void updateLights(vec4 *lightPos, vec4 *lightColor, int count) {
|
||||
//if (active.shader) {
|
||||
// active.shader->setParam(uLightColor, lightColor[0], count);
|
||||
// active.shader->setParam(uLightPos, lightPos[0], count);
|
||||
//}
|
||||
}
|
||||
|
||||
void DIP(Mesh *mesh, const MeshRange &range) {
|
||||
//
|
||||
}
|
||||
|
||||
vec4 copyPixel(int x, int y) {
|
||||
return vec4(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -571,7 +571,7 @@ struct Inventory {
|
||||
joints[1].rotate(quat(vec3(0.0f, 1.0f, 0.0f), -params.x));
|
||||
}
|
||||
|
||||
game->renderModelFull(desc.model, false, joints);
|
||||
game->renderModelFull(desc.model, joints);
|
||||
}
|
||||
|
||||
void choose() {
|
||||
@@ -1424,31 +1424,36 @@ struct Inventory {
|
||||
game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false);
|
||||
float s = 1.0f / INV_BG_SIZE;
|
||||
// vertical
|
||||
Core::setTarget(tmp, NULL, RT_STORE_COLOR);
|
||||
Core::validateRenderState();
|
||||
Core::beginRenderPass(RP_FILTER, RenderTarget(tmp), RenderTarget(NULL));
|
||||
Core::setPipelineState(PS_FILTER_BLUR);
|
||||
Core::active.shader->setParam(uParam, vec4(0, s, 0, s));
|
||||
texInOut->bind(sDiffuse);
|
||||
game->getMesh()->renderQuad();
|
||||
Core::endRenderPass();
|
||||
|
||||
// horizontal
|
||||
Core::setTarget(texInOut, NULL, RT_STORE_COLOR);
|
||||
Core::validateRenderState();
|
||||
Core::beginRenderPass(RP_FILTER, RenderTarget(texInOut), RenderTarget(NULL));
|
||||
Core::setPipelineState(PS_FILTER_BLUR);
|
||||
game->setShader(Core::passFilter, Shader::FILTER_BLUR, false, false);
|
||||
Core::active.shader->setParam(uParam, vec4(s, 0, 0, s));
|
||||
tmp->bind(sDiffuse);
|
||||
game->getMesh()->renderQuad();
|
||||
Core::endRenderPass();
|
||||
}
|
||||
|
||||
void grayscale(Texture *texIn, Texture *texOut) {
|
||||
#ifdef FFP
|
||||
return; // TODO
|
||||
#endif
|
||||
Core::beginRenderPass(RP_FILTER, RenderTarget(texOut), RenderTarget(NULL));
|
||||
Core::setPipelineState(PS_FILTER_GRAYSCALE);
|
||||
|
||||
float s = 1.0f / INV_BG_SIZE;
|
||||
game->setShader(Core::passFilter, Shader::FILTER_GRAYSCALE, false, false);
|
||||
Core::setTarget(texOut, NULL, RT_STORE_COLOR);
|
||||
Core::validateRenderState();
|
||||
Core::active.shader->setParam(uParam, vec4(0.75f, 0.75f, 1.0f, s));
|
||||
texIn->bind(sDiffuse);
|
||||
game->getMesh()->renderQuad();
|
||||
|
||||
Core::endRenderPass();
|
||||
}
|
||||
|
||||
void prepareBackground() {
|
||||
@@ -1469,9 +1474,6 @@ struct Inventory {
|
||||
|
||||
game->renderGame(false, true);
|
||||
|
||||
Core::setDepthTest(false);
|
||||
Core::setBlendMode(bmNone);
|
||||
|
||||
int viewsCount = (Core::settings.detail.stereo == Core::Settings::STEREO_OFF) ? 1 : 2;
|
||||
|
||||
mat4 mProj, mView;
|
||||
@@ -1489,8 +1491,6 @@ struct Inventory {
|
||||
#ifdef _OS_3DS
|
||||
GAPI::rotate90 = true;
|
||||
#endif
|
||||
|
||||
Core::setDepthTest(true);
|
||||
}
|
||||
|
||||
float getEyeOffset() {
|
||||
@@ -1828,9 +1828,9 @@ struct Inventory {
|
||||
} else {
|
||||
background[0]->bind(sDiffuse);
|
||||
}
|
||||
|
||||
#if 0
|
||||
Core::setBlendMode(alpha < 255 ? bmAlpha : bmNone);
|
||||
|
||||
#endif
|
||||
mat4 mProj, mView;
|
||||
mView.identity();
|
||||
mProj = GAPI::ortho(-1, +1, -1, +1, 0, 1);
|
||||
@@ -1890,18 +1890,19 @@ struct Inventory {
|
||||
|
||||
game->setShader(Core::passFilter, Shader::FILTER_UPSCALE, false, false);
|
||||
Core::active.shader->setParam(uParam, vec4(float(Core::active.textures[sDiffuse]->width), float(Core::active.textures[sDiffuse]->height), 0.0f, 0.0f));
|
||||
|
||||
#if 0
|
||||
Core::setBlendMode(phaseRing < 1.0f ? bmAlpha : bmNone);
|
||||
#endif
|
||||
game->getMesh()->renderBuffer(indices, COUNT(indices), vertices, COUNT(vertices));
|
||||
}
|
||||
|
||||
void renderBackground(int view) {
|
||||
if (!isActive() && titleTimer == 0.0f)
|
||||
return;
|
||||
|
||||
#if 0
|
||||
Core::setDepthTest(false);
|
||||
Core::setDepthWrite(false);
|
||||
|
||||
#endif
|
||||
uint8 alpha;
|
||||
if (!isActive() && titleTimer > 0.0f && titleTimer < 1.0f)
|
||||
alpha = uint8(titleTimer * 255);
|
||||
@@ -1924,10 +1925,11 @@ struct Inventory {
|
||||
else
|
||||
renderTitleBG(1.0f, sy, alpha);
|
||||
}
|
||||
|
||||
#if 0
|
||||
Core::setBlendMode(bmPremult);
|
||||
Core::setDepthTest(true);
|
||||
Core::setDepthWrite(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void setupCamera(float aspect, bool ui = false) {
|
||||
@@ -1969,7 +1971,9 @@ struct Inventory {
|
||||
|
||||
void render(float aspect) {
|
||||
if (video) {
|
||||
#if 0
|
||||
Core::setDepthTest(false);
|
||||
#endif
|
||||
video->render();
|
||||
|
||||
Texture *tmp = background[0];
|
||||
@@ -1992,8 +1996,9 @@ struct Inventory {
|
||||
renderTitleBG(1.0f, sy, clamp(int((video->stepTimer / video->step) * 255), 0, 255), 1.0f, ch);
|
||||
|
||||
background[0] = tmp;
|
||||
|
||||
#if 0
|
||||
Core::setDepthTest(true);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
|
174
src/level.h
174
src/level.h
@@ -513,7 +513,7 @@ struct Level : IGame {
|
||||
|
||||
virtual void setRoomParams(int roomIndex, Shader::Type type, float diffuse, float ambient, float specular, float alpha, bool alphaTest = false) {
|
||||
if (Core::pass == Core::passShadow) {
|
||||
setShader(Core::pass, type, false, alphaTest);
|
||||
Core::setPipelineState(alphaTest ? PS_ENTITY_SHADOW_ALPHA : PS_ENTITY_SHADOW);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -621,7 +621,7 @@ struct Level : IGame {
|
||||
GAPI::rotate90 = false;
|
||||
#endif
|
||||
|
||||
PROFILE_MARKER("ENVIRONMENT");
|
||||
PROFILE_MARKER("environment");
|
||||
setupBinding();
|
||||
float tmpEye = Core::eye;
|
||||
Core::Pass tmpPass = Core::pass;
|
||||
@@ -630,18 +630,30 @@ struct Level : IGame {
|
||||
int16 rIndex = roomIndex;
|
||||
level.getSector(rIndex, pos); // fix room index for overlapped blocks
|
||||
|
||||
Texture *depthTex = Core::acquireTarget(targets[0]->width, targets[0]->height, FMT_DEPTH);
|
||||
|
||||
// render level into cube faces or texture images
|
||||
for (int i = 0; i < 6; i++) {
|
||||
setupCubeCamera(pos, i);
|
||||
Core::pass = pass;
|
||||
|
||||
int index, face;
|
||||
|
||||
if (targets[0]->opt & OPT_CUBEMAP) {
|
||||
Core::setTarget(targets[0], NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR, i);
|
||||
index = 0;
|
||||
face = i;
|
||||
} else {
|
||||
Core::setTarget(targets[i * stride], NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR);
|
||||
index = i * stride;
|
||||
face = 0;
|
||||
}
|
||||
|
||||
Core::beginRenderPass(RP_MAIN, RenderTarget(targets[index], face, 0), RenderTarget(depthTex));
|
||||
renderView(rIndex, false, false);
|
||||
Core::endRenderPass();
|
||||
}
|
||||
|
||||
Core::releaseTarget(depthTex);
|
||||
|
||||
#ifdef _OS_3DS
|
||||
GAPI::rotate90 = true;
|
||||
#endif
|
||||
@@ -650,39 +662,19 @@ struct Level : IGame {
|
||||
Core::eye = tmpEye;
|
||||
}
|
||||
|
||||
virtual void renderModelFull(int modelIndex, bool underwater, Basis *joints) {
|
||||
virtual void renderModelFull(int modelIndex, Basis *joints) {
|
||||
vec4 ambient[6] = { vec4(0), vec4(0), vec4(0), vec4(0), vec4(0), vec4(0) };
|
||||
|
||||
// opaque
|
||||
Core::setBlendMode(bmPremult); // inventory items has fade-out/in alpha
|
||||
mesh->transparent = 0;
|
||||
setShader(Core::passCompose, Shader::ENTITY, underwater, false);
|
||||
Core::setPipelineState(PS_ENTITY_ALPHA); // inventory items has fade-out/in alpha
|
||||
Core::setBasis(joints, level.models[modelIndex].mCount);
|
||||
Core::active.shader->setParam(uMaterial, Core::active.material);
|
||||
Core::active.shader->setParam(uAmbient, ambient[0], 6);
|
||||
Core::updateLights();
|
||||
mesh->renderModel(modelIndex, underwater);
|
||||
// transparent
|
||||
mesh->transparent = 1;
|
||||
setShader(Core::passCompose, Shader::ENTITY, underwater, true);
|
||||
Core::setBasis(joints, level.models[modelIndex].mCount);
|
||||
Core::active.shader->setParam(uMaterial, Core::active.material);
|
||||
Core::active.shader->setParam(uAmbient, ambient[0], 6);
|
||||
Core::updateLights();
|
||||
mesh->renderModel(modelIndex, underwater);
|
||||
// additive
|
||||
Core::setBlendMode(bmAdd);
|
||||
Core::setDepthWrite(false);
|
||||
mesh->transparent = 2;
|
||||
setShader(Core::passCompose, Shader::ENTITY, underwater, false);
|
||||
Core::setBasis(joints, level.models[modelIndex].mCount);
|
||||
Core::active.shader->setParam(uMaterial, Core::active.material);
|
||||
Core::active.shader->setParam(uAmbient, ambient[0], 6);
|
||||
Core::updateLights();
|
||||
mesh->renderModel(modelIndex, underwater);
|
||||
Core::setDepthWrite(true);
|
||||
Core::setBlendMode(bmNone);
|
||||
mesh->transparent = 0;
|
||||
|
||||
for (int i = 0; i < 0; i++) {
|
||||
mesh->transparent = i;
|
||||
mesh->renderModel(modelIndex, false);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setEffect(Controller *controller, TR::Effect::Type effect) {
|
||||
@@ -1811,29 +1803,29 @@ struct Level : IGame {
|
||||
#endif
|
||||
ASSERT(mesh->transparent == 0);
|
||||
|
||||
Shader::Type type;
|
||||
PipelineStateType type;
|
||||
TR::SkyParams skyParams;
|
||||
|
||||
if (level.version & TR::VER_TR1) {
|
||||
if (Core::settings.detail.lighting < Core::Settings::HIGH || !Core::support.tex3D || !TR::getSkyParams(level.id, skyParams))
|
||||
return;
|
||||
type = Shader::SKY_CLOUDS_AZURE;
|
||||
type = PS_SKY_CLOUDS_AZURE;
|
||||
} else { // TR2, TR3
|
||||
if (level.extra.sky == -1)
|
||||
return;
|
||||
|
||||
if (Core::settings.detail.lighting < Core::Settings::HIGH || !Core::support.tex3D) {
|
||||
type = Shader::DEFAULT;
|
||||
type = PS_SKY;
|
||||
} else {
|
||||
type = Shader::SKY_CLOUDS;
|
||||
type = PS_SKY_CLOUDS;
|
||||
if (!TR::getSkyParams(level.id, skyParams)) {
|
||||
type = Shader::DEFAULT;
|
||||
type = PS_SKY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (type != Shader::DEFAULT && !Core::perlinTex) {
|
||||
type = Shader::DEFAULT;
|
||||
if (type != PS_SKY && !Core::perlinTex) {
|
||||
type = PS_SKY;
|
||||
if (level.version & TR::VER_TR1) {
|
||||
return;
|
||||
}
|
||||
@@ -1846,9 +1838,9 @@ struct Level : IGame {
|
||||
Core::mView.setPos(vec3(0));
|
||||
Core::setViewProj(Core::mView, Core::mProj);
|
||||
|
||||
setShader(Core::passSky, type, false, false);
|
||||
Core::setPipelineState(type);
|
||||
|
||||
if (type != Shader::DEFAULT) {
|
||||
if (type != PS_SKY) {
|
||||
float time = Core::params.x;
|
||||
if (time > SKY_TIME_PERIOD) {
|
||||
time /= SKY_TIME_PERIOD;
|
||||
@@ -1864,9 +1856,7 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
if (level.version & TR::VER_TR1) {
|
||||
Core::setCullMode(cmNone);
|
||||
mesh->renderBox();
|
||||
Core::setCullMode(cmFront);
|
||||
mesh->renderBox(); // TODO renderBoxInv
|
||||
} else {
|
||||
Basis b;
|
||||
Core::setBasis(&b, 1); // unused
|
||||
@@ -1932,7 +1922,7 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
void renderRooms(RoomDesc *roomsList, int roomsCount, int transp) {
|
||||
PROFILE_MARKER("ROOMS");
|
||||
PROFILE_MARKER("rooms");
|
||||
|
||||
if (Core::pass == Core::passShadow)
|
||||
return;
|
||||
@@ -1942,12 +1932,6 @@ struct Level : IGame {
|
||||
|
||||
Core::mModel.identity();
|
||||
|
||||
switch (transp) {
|
||||
case 0 : Core::setBlendMode(bmNone); break;
|
||||
case 1 : Core::setBlendMode(bmPremult); break;
|
||||
case 2 : Core::setBlendMode(bmAdd); Core::setDepthWrite(false); break;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
int end = roomsCount;
|
||||
int dir = 1;
|
||||
@@ -1991,13 +1975,9 @@ struct Level : IGame {
|
||||
i += dir;
|
||||
}
|
||||
|
||||
Core::setDepthWrite(true);
|
||||
|
||||
if (transp == 1) {
|
||||
atlasSprites->bind(sDiffuse);
|
||||
|
||||
Core::setBlendMode(bmPremult);
|
||||
|
||||
#ifdef MERGE_SPRITES
|
||||
basis.rot = Core::mViewInv.getRot();
|
||||
#else
|
||||
@@ -2025,7 +2005,6 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
Core::setScissor(vp);
|
||||
Core::setBlendMode(bmNone);
|
||||
}
|
||||
|
||||
void renderEntity(const TR::Entity &entity) {
|
||||
@@ -2338,7 +2317,7 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
{
|
||||
PROFILE_MARKER("ENTITY_SPRITES");
|
||||
PROFILE_MARKER("sprites");
|
||||
|
||||
if (mesh->dynICount) {
|
||||
atlasSprites->bind(sDiffuse);
|
||||
@@ -2365,36 +2344,27 @@ struct Level : IGame {
|
||||
if (Core::pass == Core::passAmbient) // TODO allow static entities
|
||||
return;
|
||||
|
||||
PROFILE_MARKER("ENTITIES");
|
||||
PROFILE_MARKER("objects");
|
||||
|
||||
if (transp == 0) {
|
||||
Core::setBlendMode(bmNone);
|
||||
renderEntitiesTransp(transp);
|
||||
}
|
||||
|
||||
if (transp == 1) {
|
||||
Core::setBlendMode(bmPremult);
|
||||
renderEntitiesTransp(transp);
|
||||
|
||||
#ifndef FFP
|
||||
Core::whiteTex->bind(sDiffuse);
|
||||
Core::setBlendMode(bmMult);
|
||||
for (int i = 0; i < level.entitiesCount; i++) {
|
||||
TR::Entity &entity = level.entities[i];
|
||||
Controller *controller = (Controller*)entity.controller;
|
||||
if (controller && controller->flags.rendered && controller->getEntity().castShadow())
|
||||
controller->renderShadow(mesh);
|
||||
}
|
||||
Core::setBlendMode(bmNone);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (transp == 2) {
|
||||
Core::setDepthWrite(false);
|
||||
Core::setBlendMode(bmAdd);
|
||||
renderEntitiesTransp(transp);
|
||||
Core::setDepthWrite(true);
|
||||
renderEntitiesTransp(transp);
|
||||
}
|
||||
|
||||
void renderBlobs() {
|
||||
PROFILE_MARKER("blobs");
|
||||
|
||||
if (Core::pass != Core::passCompose || level.isCutsceneLevel())
|
||||
return;
|
||||
|
||||
#ifndef FFP
|
||||
Core::setPipelineState(PS_BLOB);
|
||||
Core::whiteTex->bind(sDiffuse);
|
||||
for (int i = 0; i < level.entitiesCount; i++) {
|
||||
TR::Entity &entity = level.entities[i];
|
||||
Controller *controller = (Controller*)entity.controller;
|
||||
if (controller && controller->flags.rendered && controller->getEntity().castShadow())
|
||||
controller->renderShadow(mesh);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
virtual vec4 projectPoint(const vec4 &p) {
|
||||
@@ -2447,25 +2417,27 @@ struct Level : IGame {
|
||||
|
||||
if ((a.w > 0.0f) ^ (b.w > 0.0f)) {
|
||||
|
||||
if (a.x < 0.0f && b.x < 0.0f)
|
||||
if (a.x < 0.0f && b.x < 0.0f) {
|
||||
clipPort.x = -1.0f;
|
||||
else
|
||||
} else {
|
||||
if (a.x > 0.0f && b.x > 0.0f)
|
||||
clipPort.z = 1.0f;
|
||||
else {
|
||||
clipPort.x = -1.0f;
|
||||
clipPort.z = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
if (a.y < 0.0f && b.y < 0.0f)
|
||||
if (a.y < 0.0f && b.y < 0.0f) {
|
||||
clipPort.y = -1.0f;
|
||||
else
|
||||
} else {
|
||||
if (a.y > 0.0f && b.y > 0.0f)
|
||||
clipPort.w = 1.0f;
|
||||
else {
|
||||
clipPort.y = -1.0f;
|
||||
clipPort.w = 1.0f;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2530,8 +2502,8 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
virtual void renderView(int roomIndex, bool water, bool showUI, int roomsCount = 0, RoomDesc *roomsList = NULL) {
|
||||
PROFILE_MARKER("VIEW");
|
||||
|
||||
PROFILE_MARKER("view");
|
||||
#if 0
|
||||
if (water && waterCache)
|
||||
waterCache->reset();
|
||||
|
||||
@@ -2590,8 +2562,12 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
Texture *screen = NULL;
|
||||
Texture *depthTex = NULL;
|
||||
|
||||
if (water) {
|
||||
screen = (waterCache && waterCache->visible) ? waterCache->getScreenTex() : NULL;
|
||||
|
||||
Core::beginrenderPass(RP_SCENE, RenderTarget(screen), RenderTarget());
|
||||
Core::setTarget(screen, NULL, RT_CLEAR_COLOR | RT_CLEAR_DEPTH | RT_STORE_COLOR | (screen ? RT_STORE_DEPTH : 0)); // render to screen texture (FUCK YOU iOS!) or back buffer
|
||||
Core::validateRenderState();
|
||||
setupBinding();
|
||||
@@ -2601,6 +2577,7 @@ struct Level : IGame {
|
||||
|
||||
renderOpaque(roomsList, roomsCount);
|
||||
renderTransparent(roomsList, roomsCount);
|
||||
renderBlobs();
|
||||
|
||||
if (camera->isUnderwater())
|
||||
renderAdditive(roomsList, roomsCount);
|
||||
@@ -2639,6 +2616,7 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
Core::pass = pass;
|
||||
#endif
|
||||
}
|
||||
|
||||
void setupCubeCamera(const vec3 &pos, int face) {
|
||||
@@ -2804,7 +2782,7 @@ struct Level : IGame {
|
||||
}
|
||||
*/
|
||||
void renderShadows(int roomIndex, Texture *shadowMap) {
|
||||
PROFILE_MARKER("PASS_SHADOW");
|
||||
PROFILE_MARKER("shadows");
|
||||
|
||||
if (Core::settings.detail.shadows == Core::Settings::LOW)
|
||||
return;
|
||||
@@ -2816,12 +2794,14 @@ struct Level : IGame {
|
||||
|
||||
Core::pass = Core::passShadow;
|
||||
shadowMap->unbind(sShadow);
|
||||
|
||||
#if 0
|
||||
bool colorShadow = shadowMap->fmt == FMT_RGBA ? true : false;
|
||||
if (colorShadow)
|
||||
Core::setClearColor(vec4(1.0f));
|
||||
Core::setTarget(shadowMap, NULL, RT_CLEAR_DEPTH | (colorShadow ? (RT_CLEAR_COLOR | RT_STORE_COLOR) : RT_STORE_DEPTH));
|
||||
//Core::setCullMode(cmBack);
|
||||
Core::validateRenderState();
|
||||
//Core::validateRenderState();
|
||||
|
||||
/*
|
||||
if (Core::settings.detail.shadows > Core::Settings::MEDIUM) { // per-object shadow map (atlas)
|
||||
@@ -2847,7 +2827,7 @@ struct Level : IGame {
|
||||
Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_CLEAR_COLOR | RT_STORE_COLOR | RT_STORE_DEPTH);
|
||||
Core::validateRenderState();
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Core::eye = oldEye;
|
||||
}
|
||||
|
||||
@@ -3265,7 +3245,7 @@ struct Level : IGame {
|
||||
} else {
|
||||
renderEye(int(Core::eye), showUI, invBG);
|
||||
}
|
||||
|
||||
#if 0
|
||||
#ifndef _OS_3DS
|
||||
if (!invBG && Core::settings.detail.stereo == Core::Settings::STEREO_ANAGLYPH) {
|
||||
mat4 mProj, mView;
|
||||
@@ -3309,7 +3289,7 @@ struct Level : IGame {
|
||||
Core::setDepthTest(true);
|
||||
Core::setDepthWrite(true);
|
||||
}
|
||||
|
||||
#endif
|
||||
// TODO render all UI with native resolution here
|
||||
}
|
||||
|
||||
@@ -3381,7 +3361,7 @@ struct Level : IGame {
|
||||
|
||||
setDefaultTarget(eye, view, false);
|
||||
|
||||
Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR);
|
||||
//Core::setTarget(NULL, NULL, RT_CLEAR_DEPTH | RT_STORE_COLOR);
|
||||
|
||||
float aspect = setViewport(view, eye);
|
||||
|
||||
@@ -3422,6 +3402,7 @@ struct Level : IGame {
|
||||
}
|
||||
|
||||
void render() {
|
||||
#if 0
|
||||
if (isEnded && !inventory->video) {
|
||||
Core::setTarget(NULL, NULL, RT_CLEAR_COLOR | RT_STORE_COLOR);
|
||||
UI::begin(float(Core::width) / float(Core::height));
|
||||
@@ -3430,6 +3411,7 @@ struct Level : IGame {
|
||||
UI::end();
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
renderGame(true, false);
|
||||
}
|
||||
|
@@ -292,9 +292,11 @@ struct MuzzleFlash : Controller {
|
||||
game->setShader(Core::pass, Shader::FLASH, false, false);
|
||||
Core::setMaterial(lum * alpha, 0.0f, 0.0f, alpha);
|
||||
Core::setBasis(&b, 1);
|
||||
#if 0
|
||||
Core::setDepthWrite(false);
|
||||
mesh->renderModel(level->extra.muzzleFlash);
|
||||
Core::setDepthWrite(true);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1315,16 +1317,17 @@ struct Lightning : Controller {
|
||||
game->setShader(Core::pass, Shader::FLASH, false, false);
|
||||
Core::setMaterial(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
Core::setBasis(&b, 1);
|
||||
|
||||
#if 0
|
||||
Core::setCullMode(cmNone);
|
||||
Core::setBlendMode(bmAdd);
|
||||
Core::setDepthWrite(false);
|
||||
|
||||
#endif
|
||||
renderPolyline(vec3(0.0f), target - b.pos, 64.0f, 512.0f, 1);
|
||||
|
||||
#if 0
|
||||
Core::setDepthWrite(true);
|
||||
Core::setBlendMode(bmNone);
|
||||
Core::setCullMode(cmFront);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -14,7 +14,7 @@
|
||||
|
||||
#include "game.h"
|
||||
|
||||
#define WND_TITLE "OpenLara"
|
||||
#define WND_TITLE "OpenLara"
|
||||
|
||||
// timing
|
||||
unsigned int startTime;
|
||||
@@ -399,25 +399,39 @@ int main(int argc, char **argv) {
|
||||
home = getpwuid(getuid())->pw_dir;
|
||||
strcat(cacheDir, home);
|
||||
strcat(cacheDir, "/.openlara/");
|
||||
|
||||
int i = 0;
|
||||
i = i / i;
|
||||
struct stat st = {0};
|
||||
if (stat(cacheDir, &st) == -1 && mkdir(cacheDir, 0777) == -1)
|
||||
cacheDir[0] = 0;
|
||||
strcpy(saveDir, cacheDir);
|
||||
|
||||
static int XGLAttr[] = {
|
||||
GLX_RGBA,
|
||||
GLX_DOUBLEBUFFER,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
0
|
||||
};
|
||||
|
||||
Display *dpy = XOpenDisplay(NULL);
|
||||
XVisualInfo *vis = glXChooseVisual(dpy, XDefaultScreen(dpy), XGLAttr);
|
||||
XVisualInfo *vis = NULL;
|
||||
|
||||
#ifdef _GAPI_GL
|
||||
static int XGLAttr[] = {
|
||||
GLX_RGBA,
|
||||
GLX_DOUBLEBUFFER,
|
||||
GLX_DEPTH_SIZE, 24,
|
||||
GLX_RED_SIZE, 8,
|
||||
GLX_GREEN_SIZE, 8,
|
||||
GLX_BLUE_SIZE, 8,
|
||||
GLX_ALPHA_SIZE, 8,
|
||||
0
|
||||
};
|
||||
|
||||
vis = glXChooseVisual(dpy, XDefaultScreen(dpy), XGLAttr);
|
||||
|
||||
GLXContext ctx = glXCreateContext(dpy, vis, NULL, true);
|
||||
#elif _GAPI_VULKAN
|
||||
XVisualInfo visTpl;
|
||||
memset(&visTpl, 0, sizeof(visTpl));
|
||||
visTpl.screen = DefaultScreen(dpy);
|
||||
|
||||
int visCount = 0;
|
||||
vis = XGetVisualInfo(dpy, 2, &visTpl, &visCount);
|
||||
#endif
|
||||
|
||||
XSetWindowAttributes attr;
|
||||
attr.colormap = XCreateColormap(dpy, RootWindow(dpy, vis->screen), vis->visual, AllocNone);
|
||||
@@ -432,8 +446,11 @@ int main(int argc, char **argv) {
|
||||
CWColormap | CWBorderPixel | CWEventMask, &attr);
|
||||
XStoreName(dpy, wnd, WND_TITLE);
|
||||
|
||||
GLXContext ctx = glXCreateContext(dpy, vis, NULL, true);
|
||||
glXMakeCurrent(dpy, wnd, ctx);
|
||||
#ifdef _GAPI_GL
|
||||
glXMakeCurrent(dpy, wnd, ctx);
|
||||
#endif
|
||||
|
||||
XSync(dpy, false);
|
||||
XMapWindow(dpy, wnd);
|
||||
|
||||
Atom WM_DELETE_WINDOW = XInternAtom(dpy, "WM_DELETE_WINDOW", 0);
|
||||
@@ -462,7 +479,11 @@ int main(int argc, char **argv) {
|
||||
if (updated) {
|
||||
Game::render();
|
||||
Core::waitVBlank();
|
||||
glXSwapBuffers(dpy, wnd);
|
||||
#ifdef _GAPI_GL
|
||||
glXSwapBuffers(dpy, wnd);
|
||||
#elif _GAPI_VULKAN
|
||||
|
||||
#endif
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -471,7 +492,12 @@ int main(int argc, char **argv) {
|
||||
sndFree();
|
||||
Game::deinit();
|
||||
|
||||
glXMakeCurrent(dpy, 0, 0);
|
||||
XCloseDisplay(dpy);
|
||||
#ifdef _GAPI_GL
|
||||
glXMakeCurrent(dpy, 0, 0);
|
||||
XCloseDisplay(dpy);
|
||||
#elif _GAPI_VULKAN
|
||||
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -1,5 +1,7 @@
|
||||
#include "common.hlsl"
|
||||
|
||||
// ALPHA_TEST, SHADOW_DEPTH
|
||||
|
||||
struct VS_OUTPUT {
|
||||
float4 pos : POSITION;
|
||||
float4 texCoord : TEXCOORD0;
|
||||
|
38
src/ui.h
38
src/ui.h
@@ -47,7 +47,7 @@ namespace UI {
|
||||
|
||||
int advGlyphsStart;
|
||||
|
||||
#define RU_MAP "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" "i~"
|
||||
#define RU_MAP "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>" "i~"
|
||||
#define RU_GLYPH_COUNT (COUNT(RU_MAP) - 1)
|
||||
#define RU_GLYPH_START 102
|
||||
#define RU_GLYPH_UPPERCASE 20
|
||||
@@ -62,9 +62,9 @@ namespace UI {
|
||||
5, 5, 5, 11, 9, 7, 8, 6, 0, 7, 7, 3, 8, 8, 13, 7, 9, 4, 12, 12,
|
||||
7, 5, 7, 7, 7, 7, 7, 7, 7, 7, 16, 14, 14, 14, 16, 16, 16, 16, 16, 12, 14, 8, 8, 8, 8, 8, 8, 8,
|
||||
// cyrillic
|
||||
11, 11, 11, 13, 10, 13, 11, 11, 12, 12, 11, 9, 13, 13, 10, 13, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
9, 11, 12, 11, 10, 9, 8, 10, 11, 9, 10, 10, 11, 9, 10, 12, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
10, 10, 9, 11, 12, 9, 11, 8, 9, 13, 9, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
11, 11, 11, 13, 10, 13, 11, 11, 12, 12, 11, 9, 13, 13, 10, 13, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
9, 11, 12, 11, 10, 9, 8, 10, 11, 9, 10, 10, 11, 9, 10, 12, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
10, 10, 9, 11, 12, 9, 11, 8, 9, 13, 9, // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
// additional latin (i~)
|
||||
5, 10
|
||||
};
|
||||
@@ -82,10 +82,11 @@ namespace UI {
|
||||
enum Align { aLeft, aRight, aCenter, aCenterV };
|
||||
|
||||
inline int charRemap(char c) {
|
||||
#if 0
|
||||
if (isCyrillic(c)) {
|
||||
return char_map[RU_GLYPH_START + (c - '<EFBFBD>')];
|
||||
return char_map[RU_GLYPH_START + (c - 'А')];
|
||||
}
|
||||
|
||||
#endif
|
||||
if (c < 11)
|
||||
return c + 81;
|
||||
if (c < 16)
|
||||
@@ -118,11 +119,11 @@ namespace UI {
|
||||
int h = upperCase(idx) ? 13 : 9;
|
||||
int o = 0;
|
||||
char c = RU_MAP[i];
|
||||
|
||||
if (c == '<EFBFBD>' || c == '<EFBFBD>' || c == '~') h = 14;
|
||||
if (c == '<EFBFBD>' || c == '<EFBFBD>' || c == '<EFBFBD>' || c == '<EFBFBD>') { o = 1; h++; }
|
||||
if (c == '<EFBFBD>') { o = 2; h += 2; }
|
||||
|
||||
#if 0
|
||||
if (c == 'б' || c == 'д' || c == '~') h = 14;
|
||||
if (c == 'Ц' || c == 'Щ' || c == 'ц' || c == 'щ') { o = 1; h++; }
|
||||
if (c == 'ф') { o = 2; h += 2; }
|
||||
#endif
|
||||
*glyphSprite++ = TR::TextureInfo(TR::TEX_TYPE_SPRITE, 0, -h + o, w, o, (i % 16) * 16, (i / 16) * 16 + (16 - h), w, h);
|
||||
}
|
||||
// append japanese glyphs
|
||||
@@ -273,10 +274,13 @@ namespace UI {
|
||||
Core::mProj = GAPI::ortho(0.0f, width, height, 0.0f, -128.0f, 127.0f);
|
||||
Core::setViewProj(Core::mView, Core::mProj);
|
||||
|
||||
Core::setPipelineState(PS_GUI);
|
||||
#if 0
|
||||
Core::setDepthTest(false);
|
||||
Core::setDepthWrite(false);
|
||||
Core::setBlendMode(bmPremult);
|
||||
Core::setCullMode(cmNone);
|
||||
#endif
|
||||
game->setupBinding();
|
||||
|
||||
game->setShader(Core::passGUI, Shader::DEFAULT);
|
||||
@@ -291,10 +295,12 @@ namespace UI {
|
||||
|
||||
void end() {
|
||||
game->getMesh()->dynEnd();
|
||||
#if 0
|
||||
Core::setCullMode(cmFront);
|
||||
Core::setBlendMode(bmNone);
|
||||
Core::setDepthTest(true);
|
||||
Core::setDepthWrite(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
enum ShadeType {
|
||||
@@ -667,9 +673,12 @@ namespace UI {
|
||||
|
||||
Core::whiteTex->bind(sDiffuse);
|
||||
|
||||
Core::setPipelineState(PS_GUI);
|
||||
#if 0
|
||||
Core::setDepthTest(false);
|
||||
Core::setBlendMode(bmPremult);
|
||||
Core::setCullMode(cmNone);
|
||||
#endif
|
||||
|
||||
Core::mViewProj = GAPI::ortho(0.0f, float(Core::width), float(Core::height), 0.0f, 0.0f, 1.0f);
|
||||
|
||||
@@ -691,9 +700,11 @@ namespace UI {
|
||||
if (Input::btnEnable[i])
|
||||
renderControl(Input::btnPos[i], Input::btnRadius, Input::btn == i);
|
||||
|
||||
#if 0
|
||||
Core::setCullMode(cmFront);
|
||||
Core::setBlendMode(bmNone);
|
||||
Core::setDepthTest(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void renderBar(CommonTexType type, const vec2 &pos, const vec2 &size, float value, uint32 fgColor = 0xFFFFFFFF, uint32 bgColor = 0x80000000, uint32 brColor1 = 0xFF4C504C, uint32 brColor2 = 0xFF748474, uint32 fgColor2 = 0) {
|
||||
@@ -801,7 +812,7 @@ namespace UI {
|
||||
setupInventoryShading(lightOffset);
|
||||
|
||||
Basis joints[MAX_JOINTS];
|
||||
|
||||
#if 0
|
||||
Core::setDepthTest(true);
|
||||
Core::setDepthWrite(true);
|
||||
|
||||
@@ -834,7 +845,7 @@ namespace UI {
|
||||
|
||||
Core::setMaterial(1.0f, 0.0f, 0.0f, alpha);
|
||||
|
||||
game->renderModelFull(item.modelIndex - 1, false, joints);
|
||||
game->renderModelFull(item.modelIndex - 1, joints);
|
||||
}
|
||||
|
||||
Core::setDepthTest(false);
|
||||
@@ -846,6 +857,7 @@ namespace UI {
|
||||
Core::setBlendMode(bmPremult);
|
||||
Core::setCullMode(cmNone);
|
||||
Core::setMaterial(1, 1, 1, 1);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user