1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-02-24 07:22:58 +01:00

#23 split rooms geometry for alpha-test; warm up shader cache; shader optimizations

This commit is contained in:
XProger 2017-03-10 06:23:18 +03:00
parent d446887003
commit ff313dabd0
6 changed files with 206 additions and 173 deletions

View File

@ -34,51 +34,43 @@ struct ShaderCache {
ShaderCache(IGame *game) : game(game) {
memset(shaders, 0, sizeof(shaders));
/*
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");
LOG("shader: cache warm up...\n");
compile(Core::passShadow , Shader::ENTITY, false, false, false);
{
const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT" };
const char *typeNames[] = { "SPRITE", "FLASH", "ROOM", "ENTITY", "MIRROR" };
compile(Core::passAmbient, Shader::ROOM, false, false, false);
compile(Core::passAmbient, Shader::ROOM, false, true, false);
compile(Core::passAmbient, Shader::ROOM, false, false, true);
compile(Core::passAmbient, Shader::ROOM, false, true, true);
compile(Core::passAmbient, Shader::ROOM, true, false, false);
compile(Core::passAmbient, Shader::SPRITE, false, true, false);
compile(Core::passAmbient, Shader::SPRITE, false, true, true);
int animTexRangesCount = game->getMesh()->animTexRangesCount;
int animTexOffsetsCount = game->getMesh()->animTexOffsetsCount;
compile(Core::passCompose, Shader::ROOM, false, false, false);
compile(Core::passCompose, Shader::ROOM, false, true, false);
compile(Core::passCompose, Shader::ROOM, false, true, true);
compile(Core::passCompose, Shader::ROOM, false, false, true);
compile(Core::passCompose, Shader::ROOM, true, false, false);
compile(Core::passCompose, Shader::ROOM, true, false, true);
compile(Core::passCompose, Shader::ENTITY, false, false, false);
compile(Core::passCompose, Shader::ENTITY, false, false, true);
compile(Core::passCompose, Shader::ENTITY, true, false, false);
compile(Core::passCompose, Shader::ENTITY, true, false, true);
compile(Core::passCompose, Shader::SPRITE, false, true, false);
compile(Core::passCompose, Shader::SPRITE, false, true, true);
compile(Core::passCompose, Shader::SPRITE, true, true, false);
compile(Core::passCompose, Shader::SPRITE, true, true, true);
compile(Core::passCompose, Shader::FLASH, false, true, false);
for (int pass = Core::passCompose; pass <= Core::passAmbient; pass++)
for (int caustics = 0; caustics < 2; caustics++)
for (int type = Shader::SPRITE; type <= Shader::MIRROR; type++) {
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[pass][Shader::MAX * caustics + type] = new Shader(SHADER, def);
}
}
compile(Core::passFilter , Shader::FILTER_DOWNSAMPLE, false, false, false);
{
const char *typeNames[] = { "DROP", "STEP", "CAUSTICS", "MASK", "COMPOSE" };
compile(Core::passWater , Shader::WATER_MASK, false, false, false);
compile(Core::passWater , Shader::WATER_STEP, false, false, false);
compile(Core::passWater , Shader::WATER_CAUSTICS, false, false, false);
compile(Core::passWater , Shader::WATER_COMPOSE, false, false, false);
compile(Core::passWater , Shader::WATER_DROP, false, false, false);
for (int type = Shader::WATER_DROP; type <= Shader::WATER_COMPOSE; type++) {
sprintf(def, "%s#define WATER_%s\n#define WATER_FOG_DIST (1.0/%d.0)\n", ext, typeNames[type], WATER_FOG_DIST);
#ifdef WATER_USE_GRID
strcat(def, "#define WATER_USE_GRID %d\n");
#endif
shaders[Core::passWater][type] = new Shader(WATER, def);
}
}
shaders[Core::passFilter][Shader::FILTER_DOWNSAMPLE] = new Shader(FILTER, "");
*/
LOG("shader: cache is ready\n");
}
~ShaderCache() {

View File

@ -405,7 +405,7 @@ struct Lara : Character {
if (level->extra.braid > -1)
braid = new Braid(this, vec3(-4.0f, 24.0f, -48.0f));
reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
//reset(15, vec3(70067, -256, 29104), -0.68f); // level 2 (pool)
#ifdef _DEBUG
//reset(14, vec3(40448, 3584, 60928), PI * 0.5f, true); // gym (pool)
@ -2025,13 +2025,11 @@ 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);
game->setShader(Core::pass, Shader::FLASH, false, true);
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);
}
}
};

View File

@ -433,22 +433,33 @@ struct Level : IGame {
room.flags.rendered = true;
if (Core::pass != Core::passShadow) {
setRoomParams(roomIndex, intensityf(room.ambient), Shader::ROOM);
Shader *sh = Core::active.shader;
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
Basis qTemp = Core::basis;
Core::basis.translate(offset);
sh->setParam(uBasis, Core::basis);
// render room geometry
mesh->renderRoomGeometry(roomIndex);
MeshBuilder::RoomRange &range = mesh->rooms[roomIndex];
for (int transp = 0; transp < 2; transp++) {
if (!range.geometry[transp].iCount)
continue;
Core::setBlending(transp ? bmAlpha : bmNone);
setRoomParams(roomIndex, intensityf(room.ambient), Shader::ROOM, transp > 0);
Shader *sh = Core::active.shader;
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
sh->setParam(uBasis, Core::basis);
// render room geometry
mesh->renderRoomGeometry(roomIndex, transp > 0);
}
// render room sprites
if (mesh->hasRoomSprites(roomIndex)) {
if (range.sprites.iCount) {
Core::setBlending(bmAlpha);
setRoomParams(roomIndex, 1.0, Shader::SPRITE, true);
sh = Core::active.shader;
Shader *sh = Core::active.shader;
sh->setParam(uLightColor, Core::lightColor[0], MAX_LIGHTS);
sh->setParam(uLightPos, Core::lightPos[0], MAX_LIGHTS);
sh->setParam(uBasis, Core::basis);
@ -457,6 +468,7 @@ struct Level : IGame {
Core::basis = qTemp;
}
Core::setBlending(bmNone);
}
#ifdef LEVEL_EDITOR

View File

@ -134,7 +134,7 @@ struct MeshBuilder {
Mesh *mesh;
// level
struct RoomRange {
MeshRange geometry;
MeshRange geometry[2]; // opaque & transparent
MeshRange sprites;
MeshRange **meshes;
} *rooms;
@ -170,17 +170,13 @@ struct MeshBuilder {
// allocate room geometry ranges
rooms = new RoomRange[level.roomsCount];
int iCount = 0, vCount = 0, aCount = 0;
int iCount = 0, vCount = 0;
// get size of mesh for rooms (geometry & sprites)
for (int i = 0; i < level.roomsCount; i++) {
TR::Room &r = level.rooms[i];
TR::Room::Data &d = r.data;
RoomRange &range = rooms[i];
range.geometry.vStart = vCount;
range.geometry.iStart = iCount;
iCount += d.rCount * 6 + d.tCount * 3;
vCount += d.rCount * 4 + d.tCount * 3;
@ -196,20 +192,15 @@ struct MeshBuilder {
vCount += mesh.rCount * 4 + mesh.tCount * 3;
}
range.geometry.iCount = iCount - range.geometry.iStart;
ASSERT(vCount - range.geometry.vStart < 0xFFFF);
RoomRange &range = rooms[i];
range.sprites.vStart = vCount;
range.sprites.iStart = iCount;
iCount += d.sCount * 6;
vCount += d.sCount * 4;
range.sprites.iCount = iCount - range.sprites.iStart;
if (range.sprites.iCount)
aCount++;
ASSERT(vCount - range.sprites.vStart < 0xFFFF);
}
aCount += level.roomsCount;
// get models info
models = new MeshRange[level.modelsCount];
@ -219,7 +210,6 @@ struct MeshBuilder {
int index = level.meshOffsets[model.mStart + j];
if (!index && model.mStart + j > 0)
continue;
aCount++;
TR::Mesh &mesh = level.meshes[index];
iCount += mesh.rCount * 6 + mesh.tCount * 3;
vCount += mesh.rCount * 4 + mesh.tCount * 3;
@ -235,7 +225,6 @@ struct MeshBuilder {
iCount += level.spriteSequences[i].sCount * 6;
vCount += level.spriteSequences[i].sCount * 4;
}
aCount += level.spriteSequencesCount;
// get size of simple shadow spot mesh (8 triangles, 8 vertices)
shadowBlob.vStart = vCount;
@ -243,7 +232,6 @@ struct MeshBuilder {
shadowBlob.iCount = 8 * 3;
iCount += shadowBlob.iCount;
vCount += 8;
aCount++;
// bar (health, oxygen)
bar.vStart = vCount;
@ -251,7 +239,6 @@ struct MeshBuilder {
bar.iCount = 2 * 3;
iCount += bar.iCount;
vCount += 4;
aCount++;
// quad (post effect filter)
quad.vStart = vCount;
@ -259,7 +246,6 @@ struct MeshBuilder {
quad.iCount = 2 * 3;
iCount += quad.iCount;
vCount += 4;
aCount++;
// detailed plane
plane.vStart = vCount;
@ -267,72 +253,46 @@ struct MeshBuilder {
plane.iCount = PLANE_DETAIL * 2 * PLANE_DETAIL * 2 * (2 * 3);
iCount += plane.iCount;
vCount += (PLANE_DETAIL * 2 + 1) * (PLANE_DETAIL * 2 + 1);
aCount++;
// make meshes buffer (single vertex buffer object for all geometry & sprites on level)
Index *indices = new Index[iCount];
Vertex *vertices = new Vertex[vCount];
iCount = vCount = 0;
int aCount = 0;
// build rooms
for (int i = 0; i < level.roomsCount; i++) {
TR::Room &r = level.rooms[i];
TR::Room::Data &d = r.data;
TR::Room &room = level.rooms[i];
TR::Room::Data &d = room.data;
RoomRange &range = rooms[i];
// rooms geometry
int vStart = vCount;
for (int j = 0; j < d.rCount; j++) {
TR::Rectangle &f = d.rectangles[j];
TR::ObjectTexture &t = level.objectTextures[f.texture];
int vStart;
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
for (int transp = 0; transp < 2; transp++) { // opaque, opacity
range.geometry[transp].vStart = vCount;
range.geometry[transp].iStart = iCount;
addQuad(indices, iCount, vCount, vStart, vertices, &t);
vStart = vCount;
// rooms geometry
buildRoom(!transp, room, level, indices, vertices, iCount, vCount, vStart);
TR::Vertex n;
CHECK_ROOM_NORMAL(n);
// static meshes
for (int j = 0; j < room.meshesCount; j++) {
TR::Room::Mesh &m = room.meshes[j];
TR::StaticMesh *s = level.getMeshByID(m.meshID);
if (!level.meshOffsets[s->mesh]) continue;
TR::Mesh &mesh = level.meshes[level.meshOffsets[s->mesh]];
for (int k = 0; k < 4; k++) {
TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]];
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 };
vertices[vCount].normal = { n.x, n.y, n.z, 0 };
vertices[vCount].color = { 255, 255, 255, intensity(v.lighting) };
vCount++;
int x = m.x - room.info.x;
int y = m.y;
int z = m.z - room.info.z;
int d = m.rotation.value / 0x4000;
buildMesh(!transp, mesh, level, indices, vertices, iCount, vCount, vStart, 0, x, y, z, d);
}
}
range.geometry[transp].iCount = iCount - range.geometry[transp].iStart;
for (int j = 0; j < d.tCount; j++) {
TR::Triangle &f = d.triangles[j];
TR::ObjectTexture &t = level.objectTextures[f.texture];
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
addTriangle(indices, iCount, vCount, vStart, vertices, &t);
TR::Vertex n;
CHECK_ROOM_NORMAL(n);
for (int k = 0; k < 3; k++) {
auto &v = d.vertices[f.vertices[k]];
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 };
vertices[vCount].normal = { n.x, n.y, n.z, 0 };
vertices[vCount].color = { 255, 255, 255, intensity(v.lighting) };
vCount++;
}
}
// static meshes
for (int j = 0; j < r.meshesCount; j++) {
TR::Room::Mesh &m = r.meshes[j];
TR::StaticMesh *s = level.getMeshByID(m.meshID);
if (!level.meshOffsets[s->mesh]) continue;
TR::Mesh &mesh = level.meshes[level.meshOffsets[s->mesh]];
int x = m.x - r.info.x;
int y = m.y;
int z = m.z - r.info.z;
int d = m.rotation.value / 0x4000;
buildMesh(mesh, level, indices, vertices, iCount, vCount, vStart, 0, x, y, z, d);
if (range.geometry[transp].iCount)
aCount++;
}
// rooms sprites
@ -344,6 +304,8 @@ struct MeshBuilder {
addSprite(indices, vertices, iCount, vCount, vStart, v.vertex.x, v.vertex.y, v.vertex.z, sprite, intensity(v.lighting));
}
if (d.sCount) aCount++;
}
// build models geometry
@ -357,9 +319,10 @@ struct MeshBuilder {
for (int j = 0; j < model.mCount; j++) {
int index = level.meshOffsets[model.mStart + j];
if (!index && model.mStart + j > 0) continue;
aCount++;
TR::Mesh &mesh = level.meshes[index];
buildMesh(mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0);
buildMesh( true, mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0);
buildMesh(false, mesh, level, indices, vertices, iCount, vCount, vStart, j, 0, 0, 0, 0);
}
range.iCount = iCount - range.iStart;
@ -371,6 +334,7 @@ struct MeshBuilder {
TR::SpriteTexture &sprite = level.spriteTextures[level.spriteSequences[i].sStart + j];
addSprite(indices, vertices, iCount, vCount, sequences[i].vStart, 0, 0, 0, sprite, 255);
}
aCount += level.spriteSequencesCount;
// build shadow spot
for (int i = 0; i < 8; i++) {
@ -391,6 +355,7 @@ struct MeshBuilder {
}
vCount += 8;
iCount += shadowBlob.iCount;
aCount++;
// white bar
addQuad(indices, iCount, vCount, bar.vStart, vertices, &whiteTile);
@ -406,6 +371,7 @@ struct MeshBuilder {
v.texCoord = { 32688, 32688, 0, 0 };
}
vCount += 4;
aCount++;
// quad
addQuad(indices, iCount, vCount, quad.vStart, vertices, &whiteTile);
@ -421,6 +387,7 @@ struct MeshBuilder {
v.texCoord = { 32688, 32688, 0, 0 };
}
vCount += 4;
aCount++;
// plane
for (int16 j = -PLANE_DETAIL; j <= PLANE_DETAIL; j++)
@ -437,6 +404,7 @@ struct MeshBuilder {
iCount += 6;
}
}
aCount++;
LOG("MegaMesh: %d %d %d\n", iCount, vCount, aCount);
// compile buffer and ranges
@ -450,7 +418,10 @@ struct MeshBuilder {
// initialize Vertex Arrays
for (int i = 0; i < level.roomsCount; i++) {
RoomRange &r = rooms[i];
mesh->initRange(r.geometry);
if (r.geometry[0].iCount)
mesh->initRange(r.geometry[0]);
if (r.geometry[1].iCount)
mesh->initRange(r.geometry[1]);
if (r.sprites.iCount)
mesh->initRange(r.sprites);
}
@ -567,13 +538,67 @@ struct MeshBuilder {
}
}
void buildMesh(const TR::Mesh &mesh, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 joint, int x, int y, int z, int dir) {
void buildRoom(bool opaque, const TR::Room &room, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart) {
const TR::Room::Data &d = room.data;
for (int j = 0; j < d.rCount; j++) {
TR::Rectangle &f = d.rectangles[j];
TR::ObjectTexture &t = level.objectTextures[f.texture];
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
if (opaque != (t.attribute == 0))
continue;
addQuad(indices, iCount, vCount, vStart, vertices, &t);
TR::Vertex n;
CHECK_ROOM_NORMAL(n);
for (int k = 0; k < 4; k++) {
TR::Room::Data::Vertex &v = d.vertices[f.vertices[k]];
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 };
vertices[vCount].normal = { n.x, n.y, n.z, 0 };
vertices[vCount].color = { 255, 255, 255, intensity(v.lighting) };
vCount++;
}
}
for (int j = 0; j < d.tCount; j++) {
TR::Triangle &f = d.triangles[j];
TR::ObjectTexture &t = level.objectTextures[f.texture];
if (f.vertices[0] == 0xFFFF) continue; // skip if marks as unused (removing water planes)
if (opaque != (t.attribute == 0))
continue;
addTriangle(indices, iCount, vCount, vStart, vertices, &t);
TR::Vertex n;
CHECK_ROOM_NORMAL(n);
for (int k = 0; k < 3; k++) {
auto &v = d.vertices[f.vertices[k]];
vertices[vCount].coord = { v.vertex.x, v.vertex.y, v.vertex.z, 0 };
vertices[vCount].normal = { n.x, n.y, n.z, 0 };
vertices[vCount].color = { 255, 255, 255, intensity(v.lighting) };
vCount++;
}
}
}
void buildMesh(bool opaque, const TR::Mesh &mesh, const TR::Level &level, Index *indices, Vertex *vertices, int &iCount, int &vCount, int vStart, int16 joint, int x, int y, int z, int dir) {
TR::Color24 COLOR_WHITE = { 255, 255, 255 };
for (int j = 0; j < mesh.rCount; j++) {
TR::Rectangle &f = mesh.rectangles[j];
bool textured = !(f.texture & 0x8000);
TR::ObjectTexture &t = textured ? level.objectTextures[f.texture] : whiteTile;
if (opaque != (t.attribute == 0))
continue;
TR::Color24 c = textured ? COLOR_WHITE : level.getColor(f.texture);
addQuad(indices, iCount, vCount, vStart, vertices, &t);
@ -593,6 +618,10 @@ struct MeshBuilder {
TR::Triangle &f = mesh.triangles[j];
bool textured = !(f.texture & 0x8000);
TR::ObjectTexture &t = textured ? level.objectTextures[f.texture] : whiteTile;
if (opaque != (t.attribute == 0))
continue;
TR::Color24 c = textured ? COLOR_WHITE : level.getColor(f.texture);
addTriangle(indices, iCount, vCount, vStart, vertices, &t);
@ -752,18 +781,15 @@ struct MeshBuilder {
mesh->bind();
}
void renderRoomGeometry(int roomIndex) {
mesh->render(rooms[roomIndex].geometry);
void renderRoomGeometry(int roomIndex, bool transparent) {
ASSERT(rooms[roomIndex].geometry[transparent].iCount > 0);
mesh->render(rooms[roomIndex].geometry[transparent]);
}
void renderRoomSprites(int roomIndex) {
mesh->render(rooms[roomIndex].sprites);
}
bool hasRoomSprites(int roomIndex) {
return rooms[roomIndex].sprites.iCount > 0;
}
void renderModel(int modelIndex) {
mesh->render(models[modelIndex]);
}

View File

@ -22,14 +22,20 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
#ifdef PASS_COMPOSE
uniform vec3 uViewPos;
uniform int uCaustics;
uniform vec4 uParam;
uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ
#ifdef CAUSTICS
uniform vec4 uRoomSize; // xy - minXZ, zw - maxXZ
#endif
#endif
#ifdef VERTEX
uniform mat4 uViewProj;
uniform vec4 uBasis[32 * 2];
#ifdef TYPE_ENTITY
uniform vec4 uBasis[32 * 2];
#else
uniform vec4 uBasis[2];
#endif
#ifndef PASS_AMBIENT
uniform mat4 uViewInv;
@ -63,9 +69,14 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
}
void main() {
int index = int(aCoord.w) * 2;
vec4 rBasisRot = uBasis[index];
vec4 rBasisPos = uBasis[index + 1];
#ifdef TYPE_ENTITY
int index = int(aCoord.w) * 2;
vec4 rBasisRot = uBasis[index];
vec4 rBasisPos = uBasis[index + 1];
#else
vec4 rBasisRot = uBasis[0];
vec4 rBasisPos = uBasis[1];
#endif
vec4 coord = vec4(mulBasis(rBasisRot, rBasisPos, aCoord.xyz), rBasisPos.w);
@ -94,7 +105,11 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
vNormal = vec4(uViewPos.xyz - coord.xyz, 0.0);
#endif
vTexCoord.zw = clamp((coord.xz - uRoomSize.xy) / (uRoomSize.zw - uRoomSize.xy), vec2(0.0), vec2(1.0));
#ifdef CAUSTICS
vTexCoord.zw = clamp((coord.xz - uRoomSize.xy) / (uRoomSize.zw - uRoomSize.xy), vec2(0.0), vec2(1.0));
#else
vTexCoord.zw = vec2(1.0);
#endif
vViewVec = uViewPos - coord.xyz;
vLightProj = uLightProj * coord;
@ -252,27 +267,9 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
vec3 applyFog(vec3 color, vec3 fogColor, float factor) {
float fog = clamp(1.0 / exp(factor), 0.0, 1.0);
return mix(fogColor, color, fog);
// return color.xyz * exp(factor);
}
#endif
/*
float getLuminance(vec3 color) {
return dot(color.xyz, vec3(0.299, 0.587, 0.114));
}
vec3 getNormal() {
const vec2 size = vec2(2.0, 0.0);
const vec3 off = vec3(-1, 0, 1) / 1024.0;
float s01 = getLuminance(texture2D(sDiffuse, vTexCoord.xy + off.xy).xyz);
float s21 = getLuminance(texture2D(sDiffuse, vTexCoord.xy + off.zy).xyz);
float s10 = getLuminance(texture2D(sDiffuse, vTexCoord.xy + off.yx).xyz);
float s12 = getLuminance(texture2D(sDiffuse, vTexCoord.xy + off.yz).xyz);
vec3 va = vec3(size.xy * 0.25, s21-s01);
vec3 vb = vec3(size.yx * 0.25, s12-s10);
return normalize(cross(va, vb));
}
*/
void main() {
#ifndef PASS_SHADOW
#ifndef PASS_AMBIENT
@ -286,7 +283,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
vec4 color = texture2D(sDiffuse, vTexCoord.xy);
#ifdef ALPHA_TEST
if (color.w <= 0.6)
if (color.w <= 0.1)
discard;
#endif
@ -300,7 +297,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
color.xyz *= uColor.xyz;
color.xyz *= vColor.xyz;
color *= color; // to "linear" space
color.xyz *= color.xyz; // to "linear" space
#ifdef PASS_AMBIENT
color.xyz *= vColor.w;
@ -308,18 +305,11 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
// calc point lights
#ifndef TYPE_FLASH
vec3 normal = normalize(vNormal.xyz);
//vec3 n = getNormal();;
//vec3 b = normalize(cross(n, vec3(.0, -1.0, 0.0)));
//vec3 t = normalize(cross(b, n));
//normal = normalize(normal.x * t + normal.y * b + normal.z * n);
vec3 viewVec = normalize(vViewVec);
vec3 light = vec3(0.0);
// for (int i = 1; i < 3; i++) // additional lights
light += calcLight(normal, uLightPos[1], uLightColor[1]);
light += calcLight(normal, uLightPos[2], uLightColor[2]);
light += calcLight(normal, uLightPos[1], uLightColor[1]);
light += calcLight(normal, uLightPos[2], uLightColor[2]);
// apply lighting
#ifdef TYPE_SPRITE
@ -358,7 +348,7 @@ varying vec4 vTexCoord; // xy - atlas coords, zw - caustics coords
#endif
#endif
color = sqrt(color); // back to "gamma" space
color.xyz = sqrt(color.xyz); // back to "gamma" space
#ifdef PASS_COMPOSE
color.xyz = applyFog(color.xyz, vec3(0.0), length(vViewVec) * FOG_DIST);

View File

@ -14,6 +14,7 @@ const char *UniformName[uMAX] = { "uParam", "uTexParam", "uViewProj", "uViewI
struct Shader {
GLuint ID;
GLint uID[uMAX];
vec4 params[uMAX][4];
enum Type : GLint {
NONE = 0,
@ -126,6 +127,8 @@ struct Shader {
for (int ut = 0; ut < uMAX; ut++)
uID[ut] = glGetUniformLocation(ID, (GLchar*)UniformName[ut]);
memset(params, 0, sizeof(params));
}
void bind() {
@ -135,38 +138,50 @@ struct Shader {
}
}
inline bool checkParam(UniformType uType, const void *value, int size) {
return true;
/*
if (size > sizeof(vec4) * 4) return true;
if (memcmp(&params[uType], value, size) != 0) {
memcpy(&params[uType], value, size);
return true;
}
return false;
*/
}
void setParam(UniformType uType, const int &value, int count = 1) {
if (uID[uType] != -1)
glUniform1iv(uID[uType], count, (GLint*)&value);
}
void setParam(UniformType uType, const float &value, int count = 1) {
if (uID[uType] != -1)
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
glUniform1fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const vec2 &value, int count = 1) {
if (uID[uType] != -1)
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
glUniform2fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const vec3 &value, int count = 1) {
if (uID[uType] != -1)
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
glUniform3fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const vec4 &value, int count = 1) {
if (uID[uType] != -1)
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
glUniform4fv(uID[uType], count, (GLfloat*)&value);
}
void setParam(UniformType uType, const mat4 &value, int count = 1) {
if (uID[uType] != -1)
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
glUniformMatrix4fv(uID[uType], count, false, (GLfloat*)&value);
}
void setParam(UniformType uType, const Basis &value, int count = 1) {
if (uID[uType] != -1)
if (uID[uType] != -1 && checkParam(uType, &value, sizeof(value) * count))
glUniform4fv(uID[uType], count * 2, (GLfloat*)&value);
}
};