mirror of
https://github.com/XProger/OpenLara.git
synced 2025-02-24 07:22:58 +01:00
#23 on demand shader compilation, alpha test & clip plane in shader; #15 fix context backbuffer format
This commit is contained in:
parent
4e5e5c7ed9
commit
e57e2e2e9d
94
src/cache.h
94
src/cache.h
@ -6,6 +6,8 @@
|
||||
#include "controller.h"
|
||||
#include "camera.h"
|
||||
|
||||
#define NO_CLIP_PLANE 1000000.0f
|
||||
|
||||
#define FOG_DIST (18 * 1024)
|
||||
#define WATER_FOG_DIST (8 * 1024)
|
||||
//#define WATER_USE_GRID
|
||||
@ -27,10 +29,12 @@ const char GUI[] =
|
||||
;
|
||||
|
||||
struct ShaderCache {
|
||||
Shader *shaders[int(Core::passMAX) * Shader::MAX * 2];
|
||||
IGame *game;
|
||||
Shader *shaders[Core::passMAX][Shader::MAX][2][2][2];
|
||||
|
||||
ShaderCache(IGame *game) {
|
||||
ShaderCache(IGame *game) : game(game) {
|
||||
memset(shaders, 0, sizeof(shaders));
|
||||
/*
|
||||
char def[255], ext[255];
|
||||
|
||||
ext[0] = 0;
|
||||
@ -58,7 +62,7 @@ struct ShaderCache {
|
||||
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define FOG_DIST (1.0/%d.0)\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, passNames[pass], typeNames[type], MAX_LIGHTS, animTexRangesCount, animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST);
|
||||
if (caustics)
|
||||
strcat(def, "#define CAUSTICS\n");
|
||||
shaders[getIndex(Core::Pass(pass), Shader::Type(type), caustics == 1)] = new Shader(SHADER, def);
|
||||
shaders[pass][Shader::MAX * caustics + type] = new Shader(SHADER, def);
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,28 +74,84 @@ struct ShaderCache {
|
||||
#ifdef WATER_USE_GRID
|
||||
strcat(def, "#define WATER_USE_GRID %d\n");
|
||||
#endif
|
||||
shaders[getIndex(Core::passWater, Shader::Type(type), false)] = new Shader(WATER, def);
|
||||
shaders[Core::passWater][type] = new Shader(WATER, def);
|
||||
}
|
||||
}
|
||||
shaders[getIndex(Core::passFilter, Shader::FILTER_DOWNSAMPLE, false)] = new Shader(FILTER, "");
|
||||
shaders[Core::passFilter][Shader::FILTER_DOWNSAMPLE] = new Shader(FILTER, "");
|
||||
*/
|
||||
}
|
||||
|
||||
~ShaderCache() {
|
||||
for (int i = 0; i < sizeof(shaders) / sizeof(shaders[0]); i++)
|
||||
delete shaders[i];
|
||||
for (int pass = 0; pass < Core::passMAX; pass++)
|
||||
for (int type = 0; type < Shader::MAX; type++)
|
||||
for (int caustics = 0; caustics < 2; caustics++)
|
||||
for (int alphaTest = 0; alphaTest < 2; alphaTest++)
|
||||
for (int clipPlane = 0; clipPlane < 2; clipPlane++)
|
||||
delete shaders[pass][type][caustics][alphaTest][clipPlane];
|
||||
}
|
||||
|
||||
int getIndex(Core::Pass pass, Shader::Type type, bool caustics) {
|
||||
int index = int(pass) * Shader::MAX * 2 + type * 2 + int(caustics);
|
||||
ASSERT(index < sizeof(shaders) / sizeof(shaders[0]));
|
||||
return index;
|
||||
Shader* compile(Core::Pass pass, Shader::Type type, bool caustics = false, bool alphaTest = false, bool clipPlane = false) {
|
||||
char def[255], ext[255];
|
||||
ext[0] = 0;
|
||||
if (Core::support.shadowSampler) {
|
||||
#ifdef MOBILE
|
||||
strcat(ext, "#extension GL_EXT_shadow_samplers : require\n");
|
||||
#endif
|
||||
strcat(ext, "#define SHADOW_SAMPLER\n");
|
||||
} else
|
||||
if (Core::support.depthTexture)
|
||||
strcat(ext, "#define SHADOW_DEPTH\n");
|
||||
else
|
||||
strcat(ext, "#define SHADOW_COLOR\n");
|
||||
|
||||
const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT", "FILTER", "WATER" };
|
||||
const char *src = NULL;
|
||||
const char *typ = NULL;
|
||||
switch (pass) {
|
||||
case Core::passCompose :
|
||||
case Core::passShadow :
|
||||
case Core::passAmbient : {
|
||||
static const char *typeNames[] = { "SPRITE", "FLASH", "ROOM", "ENTITY", "MIRROR" };
|
||||
src = SHADER;
|
||||
typ = typeNames[type];
|
||||
int animTexRangesCount = game->getMesh()->animTexRangesCount;
|
||||
int animTexOffsetsCount = game->getMesh()->animTexOffsetsCount;
|
||||
sprintf(def, "%s#define PASS_%s\n#define TYPE_%s\n#define MAX_LIGHTS %d\n#define MAX_RANGES %d\n#define MAX_OFFSETS %d\n#define FOG_DIST (1.0/%d.0)\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, passNames[pass], typ, MAX_LIGHTS, animTexRangesCount, animTexOffsetsCount, FOG_DIST, WATER_FOG_DIST);
|
||||
if (caustics) strcat(def, "#define CAUSTICS\n");
|
||||
if (alphaTest) strcat(def, "#define ALPHA_TEST\n");
|
||||
if (clipPlane) strcat(def, "#define CLIP_PLANE\n");
|
||||
break;
|
||||
}
|
||||
case Core::passWater : {
|
||||
static const char *typeNames[] = { "DROP", "STEP", "CAUSTICS", "MASK", "COMPOSE" };
|
||||
src = WATER;
|
||||
typ = typeNames[type];
|
||||
sprintf(def, "%s#define PASS_%s\n#define WATER_%s\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, passNames[pass], typ, WATER_FOG_DIST);
|
||||
#ifdef WATER_USE_GRID
|
||||
strcat(def, "#define WATER_USE_GRID\n");
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case Core::passFilter : {
|
||||
static const char *typeNames[] = { "DOWNSAMPLE" };
|
||||
src = FILTER;
|
||||
typ = typeNames[type];
|
||||
sprintf(def, "%s#define PASS_%s\n#define FILTER_%s\n", ext, passNames[pass], typ);
|
||||
break;
|
||||
}
|
||||
default : ASSERT(false);
|
||||
}
|
||||
LOG("shader: compile %s -> %s %s%s%s\n", passNames[pass], typ, caustics ? "caustics " : "", alphaTest ? "alphaTest " : "", clipPlane ? "clipPlane" : "");
|
||||
return shaders[pass][type][caustics][alphaTest][clipPlane] = new Shader(src, def);
|
||||
}
|
||||
|
||||
void bind(Core::Pass pass, Shader::Type type, bool caustics = false) {
|
||||
void bind(Core::Pass pass, Shader::Type type, bool caustics = false, bool alphaTest = false, bool clipPlane = false) {
|
||||
Core::pass = pass;
|
||||
int index = getIndex(pass, type, caustics);
|
||||
ASSERT(shaders[index] != NULL);
|
||||
shaders[index]->bind();
|
||||
Shader *shader = shaders[pass][type][caustics][alphaTest][clipPlane];
|
||||
if (!shader)
|
||||
shader = compile(pass, type, caustics, alphaTest, clipPlane);
|
||||
ASSERT(shader != NULL);
|
||||
shader->bind();
|
||||
}
|
||||
|
||||
};
|
||||
@ -425,7 +485,7 @@ struct WaterCache {
|
||||
if (!item || !item->caustics) {
|
||||
Core::blackTex->bind(sReflect);
|
||||
Core::active.shader->setParam(uRoomSize, vec4(0.0f));
|
||||
game->setWaterParams(-10000000.0f);
|
||||
game->setWaterParams(-NO_CLIP_PLANE);
|
||||
} else {
|
||||
item->caustics->bind(sReflect);
|
||||
Core::active.shader->setParam(uRoomSize, vec4(item->pos.x - item->size.x, item->pos.z - item->size.z, item->pos.x + item->size.x, item->pos.z + item->size.z));
|
||||
@ -559,7 +619,7 @@ struct WaterCache {
|
||||
game->updateParams();
|
||||
game->renderCompose(underwater ? item.from : item.to);
|
||||
Core::invalidateTarget(false, true);
|
||||
game->setClipParams(1.0f, 1000000.0f);
|
||||
game->setClipParams(1.0f, NO_CLIP_PLANE);
|
||||
game->updateParams();
|
||||
|
||||
camera->reflectPlane = NULL;
|
||||
|
@ -24,7 +24,7 @@ struct IGame {
|
||||
virtual void setWaterParams(float height) {}
|
||||
virtual void updateParams() {}
|
||||
virtual void waterDrop(const vec3 &pos, float radius, float strength) {}
|
||||
virtual void setShader(Core::Pass pass, Shader::Type type, bool caustics) {}
|
||||
virtual void setShader(Core::Pass pass, Shader::Type type, bool caustics = false, bool alphaTest = false) {}
|
||||
virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {}
|
||||
virtual void renderCompose(int roomIndex) {}
|
||||
};
|
||||
|
@ -6,15 +6,13 @@ R"====(
|
||||
|
||||
varying vec2 vTexCoord;
|
||||
|
||||
#define FILTER_DOWNSAMPLE 0
|
||||
|
||||
uniform int uType;
|
||||
|
||||
#ifdef VERTEX
|
||||
attribute vec4 aCoord;
|
||||
|
||||
void main() {
|
||||
vTexCoord = aCoord.zw;
|
||||
vTexCoord = aCoord.zw;
|
||||
gl_Position = vec4(aCoord.xy, 0.0, 1.0);
|
||||
}
|
||||
#else
|
||||
@ -38,8 +36,10 @@ uniform int uType;
|
||||
}
|
||||
|
||||
vec4 filter() {
|
||||
if (uType == FILTER_DOWNSAMPLE) return downsample();
|
||||
return vec4(1.0, 0.0, 0.0, 1.0);
|
||||
#ifdef FILTER_DOWNSAMPLE
|
||||
return downsample();
|
||||
#endif
|
||||
return vec4(1.0, 0.0, 1.0, 1.0);
|
||||
}
|
||||
|
||||
void main() {
|
||||
|
@ -2011,11 +2011,9 @@ struct Lara : Character {
|
||||
Basis b(basis);
|
||||
b.rotate(quat(vec3(1, 0, 0), -PI * 0.5f));
|
||||
b.translate(offset);
|
||||
Core::setBlending(bmAlpha);
|
||||
Core::active.shader->setParam(uColor, vec4(lum, lum, lum, alpha));
|
||||
Core::active.shader->setParam(uBasis, b);
|
||||
mesh->renderModel(level->extra.muzzleFlash);
|
||||
Core::setBlending(bmNone);
|
||||
}
|
||||
|
||||
virtual void render(Frustum *frustum, MeshBuilder *mesh, Shader::Type type, bool caustics) {
|
||||
@ -2028,8 +2026,12 @@ struct Lara : Character {
|
||||
if (wpnCurrent != Weapon::SHOTGUN && Core::pass != Core::passShadow && (arms[0].shotTimer < MUZZLE_FLASH_TIME || arms[1].shotTimer < MUZZLE_FLASH_TIME)) {
|
||||
mat4 matrix = getMatrix();
|
||||
game->setShader(Core::pass, Shader::FLASH, false);
|
||||
Core::setBlending(bmAlpha);
|
||||
Core::setDepthWrite(false);
|
||||
renderMuzzleFlash(mesh, animation.getJoints(matrix, 10, true), vec3(-10, -50, 150), arms[0].shotTimer);
|
||||
renderMuzzleFlash(mesh, animation.getJoints(matrix, 13, true), vec3( 10, -50, 150), arms[1].shotTimer);
|
||||
Core::setBlending(bmNone);
|
||||
Core::setDepthWrite(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
41
src/level.h
41
src/level.h
@ -65,8 +65,8 @@ struct Level : IGame {
|
||||
waterCache->addDrop(pos, radius, strength);
|
||||
}
|
||||
|
||||
virtual void setShader(Core::Pass pass, Shader::Type type, bool caustics) {
|
||||
shaderCache->bind(pass, type, caustics);
|
||||
virtual void setShader(Core::Pass pass, Shader::Type type, bool caustics = false, bool alphaTest = false) {
|
||||
shaderCache->bind(pass, type, caustics, alphaTest, params.clipHeight != NO_CLIP_PLANE);
|
||||
}
|
||||
|
||||
virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {
|
||||
@ -391,7 +391,7 @@ struct Level : IGame {
|
||||
}
|
||||
#endif
|
||||
|
||||
void setRoomParams(int roomIndex, float intensity, Shader::Type type) {
|
||||
void setRoomParams(int roomIndex, float intensity, Shader::Type type, bool alphaTest = false) {
|
||||
if (Core::pass == Core::passShadow) {
|
||||
setShader(Core::pass, type, false);
|
||||
return;
|
||||
@ -399,7 +399,7 @@ struct Level : IGame {
|
||||
|
||||
TR::Room &room = level.rooms[roomIndex];
|
||||
|
||||
setShader(Core::pass, type, room.flags.water);
|
||||
setShader(Core::pass, type, room.flags.water, alphaTest);
|
||||
|
||||
if (room.flags.water) {
|
||||
Core::color = vec4(waterCache->color, intensity);
|
||||
@ -447,7 +447,7 @@ struct Level : IGame {
|
||||
|
||||
// render room sprites
|
||||
if (mesh->hasRoomSprites(roomIndex)) {
|
||||
setRoomParams(roomIndex, 1.0, Shader::SPRITE);
|
||||
setRoomParams(roomIndex, 1.0, Shader::SPRITE, true);
|
||||
sh = Core::active.shader;
|
||||
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
|
||||
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
|
||||
@ -554,7 +554,7 @@ struct Level : IGame {
|
||||
if (entity.type == TR::Entity::CRYSTAL)
|
||||
type = Shader::MIRROR;
|
||||
|
||||
setRoomParams(entity.room, isModel ? controller->specular : intensityf(lum), type);
|
||||
setRoomParams(entity.room, isModel ? controller->specular : intensityf(lum), type, !isModel);
|
||||
|
||||
if (isModel) { // model
|
||||
vec3 pos = controller->getPos();
|
||||
@ -615,18 +615,21 @@ struct Level : IGame {
|
||||
if (!Core::support.VAO)
|
||||
mesh->bind();
|
||||
//Core::mViewProj = Core::mLightProj;
|
||||
// set frame constants for all shaders
|
||||
for (int i = 0; i < sizeof(shaderCache->shaders) / sizeof(shaderCache->shaders[0]); i++) {
|
||||
Shader *sh = shaderCache->shaders[i];
|
||||
if (!sh) continue;
|
||||
sh->bind();
|
||||
sh->setParam(uViewProj, Core::mViewProj);
|
||||
sh->setParam(uLightProj, Core::mLightProj);
|
||||
sh->setParam(uViewInv, Core::mViewInv);
|
||||
sh->setParam(uViewPos, Core::viewPos);
|
||||
sh->setParam(uParam, *((vec4*)¶ms));
|
||||
sh->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount);
|
||||
sh->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount);
|
||||
// set frame constants for all shaders
|
||||
for (int i = 0; i < sizeof(shaderCache->shaders[Core::pass]) / sizeof(shaderCache->shaders[Core::pass][0]); i++) {
|
||||
Shader **ptr = &shaderCache->shaders[Core::pass][i][0][0][0];
|
||||
for (int j = 0; j < 8; j++) {
|
||||
Shader *sh = *ptr++;
|
||||
if (!sh) continue;
|
||||
sh->bind();
|
||||
sh->setParam(uViewProj, Core::mViewProj);
|
||||
sh->setParam(uLightProj, Core::mLightProj);
|
||||
sh->setParam(uViewInv, Core::mViewInv);
|
||||
sh->setParam(uViewPos, Core::viewPos);
|
||||
sh->setParam(uParam, *((vec4*)¶ms));
|
||||
sh->setParam(uAnimTexRanges, mesh->animTexRanges[0], mesh->animTexRangesCount);
|
||||
sh->setParam(uAnimTexOffsets, mesh->animTexOffsets[0], mesh->animTexOffsetsCount);
|
||||
}
|
||||
}
|
||||
Core::basis.identity();
|
||||
|
||||
@ -728,7 +731,7 @@ struct Level : IGame {
|
||||
|
||||
void render() {
|
||||
Core::invalidateTarget(true, true);
|
||||
params.clipHeight = 1000000.0f;
|
||||
params.clipHeight = NO_CLIP_PLANE;
|
||||
params.clipSign = 1.0f;
|
||||
params.waterHeight = params.clipHeight;
|
||||
Core::resetStates();
|
||||
|
@ -44,7 +44,7 @@ public class MainActivity extends Activity implements OnTouchListener, OnGeneric
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
view = new GLSurfaceView(this);
|
||||
view.setEGLConfigChooser(5, 6, 5, 0, 16, 0);
|
||||
view.setEGLConfigChooser(8, 8, 8, 8, 16, 0);
|
||||
view.setEGLContextClientVersion(2);
|
||||
view.setRenderer(wrapper = new Wrapper());
|
||||
|
||||
|
@ -276,7 +276,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
void main() {
|
||||
#ifndef PASS_SHADOW
|
||||
#ifndef PASS_AMBIENT
|
||||
#if defined(TYPE_ENTITY) && defined(CAUSTICS)
|
||||
#ifdef CLIP_PLANE
|
||||
if (vCoord.y * uParam.z > uParam.w)
|
||||
discard;
|
||||
#endif
|
||||
@ -353,7 +353,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
|
||||
|
||||
#else // ifndef TYPE_FLASH
|
||||
|
||||
color.w = uColor.w;
|
||||
color.w *= uColor.w;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user