1
0
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:
xproger
2020-06-17 04:44:07 +03:00
parent c3bf394e29
commit aa3ab6e9ba
12 changed files with 1119 additions and 323 deletions

View File

@@ -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);
}

View File

@@ -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() {

View File

@@ -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);

View File

@@ -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;

View File

@@ -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);

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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
}
};

View File

@@ -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;
}

View File

@@ -1,5 +1,7 @@
#include "common.hlsl"
// ALPHA_TEST, SHADOW_DEPTH
struct VS_OUTPUT {
float4 pos : POSITION;
float4 texCoord : TEXCOORD0;

View File

@@ -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
}
};