1
0
mirror of https://github.com/XProger/OpenLara.git synced 2025-08-12 08:04:09 +02:00

#23 shadow mask (volumes); #15 android fix double tap

This commit is contained in:
XProger
2017-03-26 03:01:31 +03:00
parent b481719277
commit 0380184967
8 changed files with 237 additions and 56 deletions

View File

@@ -17,12 +17,16 @@ const char SHADER[] =
#include "shader.glsl" #include "shader.glsl"
; ;
const char WATER[] =
#include "water.glsl"
;
const char FILTER[] = const char FILTER[] =
#include "filter.glsl" #include "filter.glsl"
; ;
const char WATER[] = const char VOLUME[] =
#include "water.glsl" #include "volume.glsl"
; ;
const char GUI[] = const char GUI[] =
@@ -113,7 +117,7 @@ struct ShaderCache {
} }
} }
const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT", "WATER", "FILTER", "GUI" }; const char *passNames[] = { "COMPOSE", "SHADOW", "AMBIENT", "WATER", "FILTER", "VOLUME", "GUI" };
const char *src = NULL; const char *src = NULL;
const char *typ = NULL; const char *typ = NULL;
switch (pass) { switch (pass) {
@@ -146,12 +150,19 @@ struct ShaderCache {
break; break;
} }
case Core::passFilter : { case Core::passFilter : {
static const char *typeNames[] = { "DOWNSAMPLE" }; static const char *typeNames[] = { "DEFAULT", "DOWNSAMPLE" };
src = FILTER; src = FILTER;
typ = typeNames[type]; typ = typeNames[type];
sprintf(def, "%s#define PASS_%s\n#define FILTER_%s\n", ext, passNames[pass], typ); sprintf(def, "%s#define PASS_%s\n#define FILTER_%s\n", ext, passNames[pass], typ);
break; break;
} }
case Core::passVolume : {
static const char *typeNames[] = { "DEFAULT" };
src = VOLUME;
typ = typeNames[type];
sprintf(def, "%s#define PASS_%s\n", ext, passNames[pass]);
break;
}
case Core::passGUI : { case Core::passGUI : {
static const char *typeNames[] = { "DEFAULT" }; static const char *typeNames[] = { "DEFAULT" };
src = GUI; src = GUI;

View File

@@ -26,7 +26,7 @@ struct IGame {
virtual void waterDrop(const vec3 &pos, float radius, float strength) {} virtual void waterDrop(const vec3 &pos, float radius, float strength) {}
virtual void setShader(Core::Pass pass, Shader::Type type, bool underwater = false, bool alphaTest = false) {} virtual void setShader(Core::Pass pass, Shader::Type type, bool underwater = false, bool alphaTest = false) {}
virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {} virtual void renderEnvironment(int roomIndex, const vec3 &pos, Texture **targets, int stride = 0) {}
virtual void renderCompose(int roomIndex) {} virtual void renderCompose(int roomIndex, bool genShadowMask = false) {}
}; };
struct Controller { struct Controller {
@@ -489,23 +489,6 @@ struct Controller {
} }
void renderShadow(MeshBuilder *mesh, const vec3 &pos, const vec3 &offset, const vec3 &size, float angle) { void renderShadow(MeshBuilder *mesh, const vec3 &pos, const vec3 &offset, const vec3 &size, float angle) {
/*
mat4 m;
m.identity();
m.translate(pos);
m.rotateY(angle);
m.translate(vec3(offset.x, 0.0f, offset.z));
m.scale(vec3(size.x, 0.0f, size.z) * (1.0f / 1024.0f));
game->setShader(Core::pass, Shader::FLASH, false, false);
Core::active.shader->setParam(uBasis, Basis(m));
Core::active.shader->setParam(uColor, vec4(0.5f, 0.5f, 0.5f, 1.0f));
Core::active.shader->setParam(uAmbient, vec3(0.0f));
Core::setBlending(bmMultiply);
mesh->renderShadowSpot();
Core::setBlending(bmNone);
*/
mat4 m = Core::mViewProj; mat4 m = Core::mViewProj;
m.translate(pos); m.translate(pos);
m.rotateY(angle); m.rotateY(angle);
@@ -522,7 +505,7 @@ struct Controller {
Core::active.shader->setParam(uAmbient, vec3(0.0f)); Core::active.shader->setParam(uAmbient, vec3(0.0f));
Core::setBlending(bmAlpha); Core::setBlending(bmAlpha);
mesh->renderShadowSpot(); mesh->renderShadowBlob();
Core::setBlending(bmNone); Core::setBlending(bmNone);
Core::active.shader->setParam(uViewProj, Core::mViewProj); Core::active.shader->setParam(uViewProj, Core::mViewProj);

View File

@@ -79,8 +79,10 @@
#define GL_RGBA16F GL_RGBA #define GL_RGBA16F GL_RGBA
#define GL_HALF_FLOAT GL_HALF_FLOAT_OES #define GL_HALF_FLOAT GL_HALF_FLOAT_OES
#define glGetProgramBinary(...) 0 #define GL_STENCIL_TEST_TWO_SIDE_EXT 0
#define glProgramBinary(...) 0 #define glGetProgramBinary(...)
#define glProgramBinary(...)
#define glActiveStencilFaceEXT(...)
#endif #endif
#include "utils.h" #include "utils.h"
@@ -158,6 +160,10 @@
PFNGLDELETEBUFFERSARBPROC glDeleteBuffers; PFNGLDELETEBUFFERSARBPROC glDeleteBuffers;
PFNGLBINDBUFFERARBPROC glBindBuffer; PFNGLBINDBUFFERARBPROC glBindBuffer;
PFNGLBUFFERDATAARBPROC glBufferData; PFNGLBUFFERDATAARBPROC glBufferData;
// Stencil
PFNGLACTIVESTENCILFACEEXTPROC glActiveStencilFaceEXT;
PFNGLSTENCILFUNCSEPARATEPROC glStencilFuncSeparate;
PFNGLSTENCILOPSEPARATEPROC glStencilOpSeparate;
#endif #endif
PFNGLGENVERTEXARRAYSPROC glGenVertexArrays; PFNGLGENVERTEXARRAYSPROC glGenVertexArrays;
@@ -180,6 +186,7 @@ struct Texture;
namespace Core { namespace Core {
struct { struct {
bool shaderBinary;
bool VAO; bool VAO;
bool depthTexture; bool depthTexture;
bool shadowSampler; bool shadowSampler;
@@ -187,7 +194,7 @@ namespace Core {
bool texNPOT; bool texNPOT;
bool texFloat, texFloatLinear; bool texFloat, texFloatLinear;
bool texHalf, texHalfLinear; bool texHalf, texHalfLinear;
bool shaderBinary; char stencil;
#ifdef PROFILE #ifdef PROFILE
bool profMarker; bool profMarker;
bool profTiming; bool profTiming;
@@ -254,7 +261,7 @@ namespace Core {
Texture *blackTex, *whiteTex; Texture *blackTex, *whiteTex;
enum Pass { passCompose, passShadow, passAmbient, passWater, passFilter, passGUI, passMAX } pass; enum Pass { passCompose, passShadow, passAmbient, passWater, passFilter, passVolume, passGUI, passMAX } pass;
GLuint FBO; GLuint FBO;
struct RenderTargetCache { struct RenderTargetCache {
@@ -274,6 +281,7 @@ namespace Core {
GLuint VAO; GLuint VAO;
BlendMode blendMode; BlendMode blendMode;
CullMode cullMode; CullMode cullMode;
bool stencilTwoSide;
} active; } active;
struct Stats { struct Stats {
@@ -312,7 +320,6 @@ namespace Core {
#include "texture.h" #include "texture.h"
#include "shader.h" #include "shader.h"
#include "mesh.h"
namespace Core { namespace Core {
@@ -379,6 +386,10 @@ namespace Core {
GetProcOGL(glDeleteBuffers); GetProcOGL(glDeleteBuffers);
GetProcOGL(glBindBuffer); GetProcOGL(glBindBuffer);
GetProcOGL(glBufferData); GetProcOGL(glBufferData);
GetProcOGL(glActiveStencilFaceEXT);
GetProcOGL(glStencilFuncSeparate);
GetProcOGL(glStencilOpSeparate);
#endif #endif
#ifdef MOBILE #ifdef MOBILE
@@ -395,7 +406,7 @@ namespace Core {
char *ext = (char*)glGetString(GL_EXTENSIONS); char *ext = (char*)glGetString(GL_EXTENSIONS);
//LOG("%s\n", ext); //LOG("%s\n", ext);
support.shaderBinary = extSupport(ext, "_program_binary"); support.shaderBinary = false;//extSupport(ext, "_program_binary");
support.VAO = extSupport(ext, "_vertex_array_object"); support.VAO = extSupport(ext, "_vertex_array_object");
support.depthTexture = extSupport(ext, "_depth_texture"); support.depthTexture = extSupport(ext, "_depth_texture");
support.shadowSampler = extSupport(ext, "_shadow_samplers") || extSupport(ext, "GL_ARB_shadow"); support.shadowSampler = extSupport(ext, "_shadow_samplers") || extSupport(ext, "GL_ARB_shadow");
@@ -405,6 +416,15 @@ namespace Core {
support.texFloat = support.texFloatLinear || extSupport(ext, "_texture_float"); support.texFloat = support.texFloatLinear || extSupport(ext, "_texture_float");
support.texHalfLinear = extSupport(ext, "GL_ARB_texture_float") || extSupport(ext, "_texture_half_float_linear"); support.texHalfLinear = extSupport(ext, "GL_ARB_texture_float") || extSupport(ext, "_texture_half_float_linear");
support.texHalf = support.texHalfLinear || extSupport(ext, "_texture_half_float"); support.texHalf = support.texHalfLinear || extSupport(ext, "_texture_half_float");
if (extSupport(ext, "_ATI_separate_stencil"))
support.stencil = 2;
else
if (extSupport(ext, "_stencil_two_side"))
support.stencil = 1;
else
support.stencil = 0;
#ifdef PROFILE #ifdef PROFILE
support.profMarker = extSupport(ext, "_KHR_debug"); support.profMarker = extSupport(ext, "_KHR_debug");
support.profTiming = extSupport(ext, "_timer_query"); support.profTiming = extSupport(ext, "_timer_query");
@@ -425,6 +445,7 @@ namespace Core {
LOG(" float textures : float = %s, half = %s\n", LOG(" float textures : float = %s, half = %s\n",
support.texFloat ? (support.texFloatLinear ? "linear" : "nearest") : "false", support.texFloat ? (support.texFloatLinear ? "linear" : "nearest") : "false",
support.texHalf ? (support.texHalfLinear ? "linear" : "nearest") : "false"); support.texHalf ? (support.texHalfLinear ? "linear" : "nearest") : "false");
LOG(" stencil : %s\n", support.stencil == 2 ? "separate" : (support.stencil == 1 ? "two_side" : "false"));
LOG("\n"); LOG("\n");
glGenFramebuffers(1, &FBO); glGenFramebuffers(1, &FBO);
@@ -472,14 +493,14 @@ namespace Core {
item.height = height; item.height = height;
glBindRenderbuffer(GL_RENDERBUFFER, item.ID); glBindRenderbuffer(GL_RENDERBUFFER, item.ID);
glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_RGB : GL_DEPTH_COMPONENT16, width, height); glRenderbufferStorage(GL_RENDERBUFFER, depth ? GL_RGB565 : GL_DEPTH_COMPONENT16, width, height);
glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindRenderbuffer(GL_RENDERBUFFER, 0);
return cache.count++; return cache.count++;
} }
void clear(bool clearColor, bool clearDepth) { void clear(bool clearColor, bool clearDepth, bool clearStencil = false) {
if (GLbitfield mask = (clearColor ? GL_COLOR_BUFFER_BIT : 0) | (clearDepth ? GL_DEPTH_BUFFER_BIT : 0)) if (GLbitfield mask = (clearColor ? GL_COLOR_BUFFER_BIT : 0) | (clearDepth ? GL_DEPTH_BUFFER_BIT : 0) | (clearStencil ? GL_STENCIL_BUFFER_BIT : 0))
glClear(mask); glClear(mask);
} }
@@ -487,6 +508,10 @@ namespace Core {
glClearColor(color.x, color.y, color.z, color.w); glClearColor(color.x, color.y, color.z, color.w);
} }
void setClearStencil(int value) {
glClearStencil(value);
}
void setViewport(int x, int y, int width, int height) { void setViewport(int x, int y, int width, int height) {
glViewport(x, y, width, height); glViewport(x, y, width, height);
} }
@@ -555,6 +580,47 @@ namespace Core {
glDisable(GL_DEPTH_TEST); glDisable(GL_DEPTH_TEST);
} }
void setStencilTest(bool test) {
if (test)
glEnable(GL_STENCIL_TEST);
else
glDisable(GL_STENCIL_TEST);
}
void setStencilTwoSide(int ref, bool test) { // preset for z-fail shadow volumes
active.stencilTwoSide = test;
if (test) {
switch (Core::support.stencil) {
case 0 :
glStencilFunc(GL_ALWAYS, ref, ~0);
break;
case 1 :
setCulling(cfNone);
glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
glActiveStencilFaceEXT(GL_BACK);
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
glStencilFunc(GL_ALWAYS, ref, ~0);
glActiveStencilFaceEXT(GL_FRONT);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
glStencilFunc(GL_ALWAYS, ref, ~0);
break;
case 2 :
setCulling(cfNone);
glStencilFuncSeparate(GL_FRONT, GL_ALWAYS, ref, ~0);
glStencilFuncSeparate(GL_BACK, GL_ALWAYS, ref, ~0);
glStencilOpSeparate(GL_FRONT, GL_KEEP, GL_INCR, GL_KEEP);
glStencilOpSeparate(GL_BACK, GL_KEEP, GL_DECR, GL_KEEP);
break;
}
} else {
if (Core::support.stencil == 1)
glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glStencilFunc(GL_NOTEQUAL, ref, ~0);
setCulling(cfFront);
}
}
void invalidateTarget(bool color, bool depth) { void invalidateTarget(bool color, bool depth) {
#ifdef MOBILE #ifdef MOBILE
if (support.discardFrame && (color || depth)) { if (support.discardFrame && (color || depth)) {
@@ -619,4 +685,6 @@ namespace Core {
} }
} }
#include "mesh.h"
#endif #endif

View File

@@ -86,7 +86,7 @@ struct Level : IGame {
} }
} }
virtual void renderCompose(int roomIndex) { virtual void renderCompose(int roomIndex, bool genShadowMask = false) {
PROFILE_MARKER("PASS_COMPOSE"); PROFILE_MARKER("PASS_COMPOSE");
Core::pass = Core::passCompose; Core::pass = Core::passCompose;
@@ -95,6 +95,51 @@ struct Level : IGame {
if (shadow) if (shadow)
shadow->bind(sShadow); shadow->bind(sShadow);
renderScene(roomIndex); renderScene(roomIndex);
if (genShadowMask) {
// renderShadowVolumes();
}
}
void renderShadowVolumes() {
getLight(lara->pos, lara->getRoomIndex());
Core::setCulling(cfNone);
Core::setDepthWrite(false);
Core::setColorWrite(false, false, false, false);
Core::setStencilTest(true);
Core::setStencilTwoSide(128, true);
setShader(Core::passVolume, Shader::DEFAULT, false, false);
vec4 lp(Core::lightPos[0], Core::lightColor[0].w);
Core::active.shader->setParam(uLightPos, lp);
for (int i = 0; i < level.entitiesCount; i++) {
TR::Entity &e = level.entities[i];
if (e.flags.rendered && TR::castShadow(e.type)) {
Controller *controller = (Controller*)e.controller;
mat4 matrix = controller->getMatrix();
Box box = controller->animation.getBoundingBox(vec3(0.0f), 0);
matrix.translate(box.center());
Core::active.shader->setParam(uBasis, Basis(matrix) );
Core::active.shader->setParam(uPosScale, box.size() * 0.5);
mesh->renderShadowBox();
}
}
Core::setDepthWrite(true);
Core::setColorWrite(true, true, true, true);
Core::setStencilTwoSide(128, false);
setShader(Core::passFilter, Shader::DEFAULT, false, false);
mesh->renderQuad();
Core::setStencilTest(false);
} }
//============================== //==============================
@@ -739,14 +784,15 @@ struct Level : IGame {
if (shadow) if (shadow)
renderShadows(lara->getRoomIndex()); renderShadows(lara->getRoomIndex());
Core::setClearStencil(128);
Core::setTarget(NULL); Core::setTarget(NULL);
Core::clear(true, true); Core::clear(true, true, true);
Core::setViewport(0, 0, Core::width, Core::height); Core::setViewport(0, 0, Core::width, Core::height);
if (waterCache) if (waterCache)
waterCache->checkVisibility = true; waterCache->checkVisibility = true;
renderCompose(camera->getRoomIndex()); renderCompose(camera->getRoomIndex(), true);
if (waterCache) { if (waterCache) {
waterCache->checkVisibility = false; waterCache->checkVisibility = false;
@@ -825,7 +871,7 @@ struct Level : IGame {
Core::setDepthTest(true); Core::setDepthTest(true);
/*
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
glPushMatrix(); glPushMatrix();
glLoadIdentity(); glLoadIdentity();

View File

@@ -90,13 +90,25 @@ struct Mesh {
glEnableVertexAttribArray(aColor); glEnableVertexAttribArray(aColor);
} }
void render(const MeshRange &range) { void DIP(const MeshRange &range) {
range.bind(VAO);
glDrawElements(GL_TRIANGLES, range.iCount, GL_UNSIGNED_SHORT, (GLvoid*)(range.iStart * sizeof(Index))); glDrawElements(GL_TRIANGLES, range.iCount, GL_UNSIGNED_SHORT, (GLvoid*)(range.iStart * sizeof(Index)));
Core::stats.dips++; Core::stats.dips++;
Core::stats.tris += range.iCount / 3; Core::stats.tris += range.iCount / 3;
} }
void render(const MeshRange &range) {
range.bind(VAO);
if (Core::active.stencilTwoSide && Core::support.stencil == 0) {
Core::setCulling(cfBack);
glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
DIP(range);
Core::setCulling(cfFront);
glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
}
DIP(range);
}
}; };
@@ -145,7 +157,7 @@ struct MeshBuilder {
} *models; } *models;
MeshRange *sequences; MeshRange *sequences;
// procedured // procedured
MeshRange shadowBlob; MeshRange shadowBlob, shadowBox;
MeshRange bar; MeshRange bar;
MeshRange quad, circle; MeshRange quad, circle;
MeshRange plane; MeshRange plane;
@@ -231,13 +243,20 @@ struct MeshBuilder {
vCount += level.spriteSequences[i].sCount * 4; vCount += level.spriteSequences[i].sCount * 4;
} }
// get size of simple shadow spot mesh (8 triangles, 8 vertices) // shadow blob mesh (8 triangles, 8 vertices)
shadowBlob.vStart = vCount; shadowBlob.vStart = vCount;
shadowBlob.iStart = iCount; shadowBlob.iStart = iCount;
shadowBlob.iCount = 8 * 3; shadowBlob.iCount = 8 * 3;
iCount += shadowBlob.iCount; iCount += shadowBlob.iCount;
vCount += 8; vCount += 8;
// shadow box (for stencil shadow volumes with degenerate triangles)
shadowBox.vStart = vCount;
shadowBox.iStart = iCount;
shadowBox.iCount = (3 * (2 + 4)) * 6;
iCount += shadowBox.iCount;
vCount += 4 * 6;
// bar (health, oxygen) // bar (health, oxygen)
bar.vStart = vCount; bar.vStart = vCount;
bar.iStart = iCount; bar.iStart = iCount;
@@ -350,7 +369,7 @@ struct MeshBuilder {
} }
aCount += level.spriteSequencesCount; aCount += level.spriteSequencesCount;
// build shadow spot // build shadow blob
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
Vertex &v = vertices[vCount + i]; Vertex &v = vertices[vCount + i];
v.normal = { 0, -1, 0, 1 }; v.normal = { 0, -1, 0, 1 };
@@ -371,6 +390,59 @@ struct MeshBuilder {
iCount += shadowBlob.iCount; iCount += shadowBlob.iCount;
aCount++; aCount++;
// build shadow box volume
{
static const Index tmpIndices[] = {
0,1,2, 0,2,3, 0,7,1, 0,4,7,
1,11,2, 1,8,11, 2,15,3, 2,12,15,
3,19,0, 3,16,19, 21,6,5, 21,20,6,
20,10,9, 20,23,10, 23,14,13, 23,22,14,
22,18,17, 22,21,18, 20,21,22, 20,22,23,
7,6,9, 7,9,8, 11,10,13, 11,13,12,
15,14,17, 15,17,16, 19,5,4, 19,18,5,
4,6,7, 4,5,6, 8,9,10, 8,10,11,
12,14,15, 12,13,14, 16,18,19, 16,17,18
};
static const short4 tmpCoords[] = {
{ -1, -1, -1, 0 }, { 1, -1, -1, 0 }, { 1, 1, -1, 0 }, { -1, 1, -1, 0 },
{ -1, -1, -1, 0 }, { -1, -1, 1, 0 }, { 1, -1, 1, 0 }, { 1, -1, -1, 0 },
{ 1, -1, -1, 0 }, { 1, -1, 1, 0 }, { 1, 1, 1, 0 }, { 1, 1, -1, 0 },
{ 1, 1, -1, 0 }, { 1, 1, 1, 0 }, { -1, 1, 1, 0 }, { -1, 1, -1, 0 },
{ -1, 1, -1, 0 }, { -1, 1, 1, 0 }, { -1, -1, 1, 0 }, { -1, -1, -1, 0 },
{ 1, -1, 1, 0 }, { -1, -1, 1, 0 }, { -1, 1, 1, 0 }, { 1, 1, 1, 0 },
};
const short n = 32767;
static const short4 tmpNormals[] = {
{ 0, 0, -n, 0 },
{ 0, -n, 0, 0 },
{ n, 0, 0, 0 },
{ 0, n, 0, 0 },
{ -n, 0, 0, 0 },
{ 0, 0, n, 0 },
};
static const ubyte4 tmpColors[] = {
{ 255, 0, 0, 0 },
{ 0, 255, 0, 0 },
{ 0, 0, 255, 0 },
{ 255, 0, 255, 0 },
{ 255, 255, 0, 0 },
{ 0, 255, 255, 0 },
};
memcpy(&indices[iCount], &tmpIndices[0], shadowBox.iCount * sizeof(Index));
memset(&vertices[vCount], 0, 4 * 6 * sizeof(Vertex));
for (int i = 0; i < 4 * 6; i++) {
vertices[vCount + i].coord = tmpCoords[i];
vertices[vCount + i].normal = tmpNormals[i / 4];
vertices[vCount + i].color = tmpColors[i / 4];
}
iCount += shadowBox.iCount;
vCount += 4 * 6;
aCount++;
}
// white bar // white bar
addQuad(indices, iCount, vCount, bar.vStart, vertices, &whiteTile); addQuad(indices, iCount, vCount, bar.vStart, vertices, &whiteTile);
vertices[vCount + 0].coord = { 0, 0, 0, 0 }; vertices[vCount + 0].coord = { 0, 0, 0, 0 };
@@ -467,6 +539,7 @@ struct MeshBuilder {
for (int i = 0; i < level.modelsCount; i++) for (int i = 0; i < level.modelsCount; i++)
mesh->initRange(models[i].geometry); mesh->initRange(models[i].geometry);
mesh->initRange(shadowBlob); mesh->initRange(shadowBlob);
mesh->initRange(shadowBox);
mesh->initRange(bar); mesh->initRange(bar);
mesh->initRange(quad); mesh->initRange(quad);
mesh->initRange(circle); mesh->initRange(circle);
@@ -856,12 +929,12 @@ struct MeshBuilder {
mesh->render(range); mesh->render(range);
} }
void renderShadowSpot() { void renderShadowBlob() {
mesh->render(shadowBlob); mesh->render(shadowBlob);
} }
void renderLine(const vec2 &pos, const vec2 &size, uint32 color) { void renderShadowBox() {
mesh->render(shadowBox);
} }
void renderQuad() { void renderQuad() {

View File

@@ -218,6 +218,7 @@
<None Include="..\..\filter.glsl" /> <None Include="..\..\filter.glsl" />
<None Include="..\..\gui.glsl" /> <None Include="..\..\gui.glsl" />
<None Include="..\..\shader.glsl" /> <None Include="..\..\shader.glsl" />
<None Include="..\..\volume.glsl" />
<None Include="..\..\water.glsl" /> <None Include="..\..\water.glsl" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View File

@@ -57,9 +57,9 @@ struct Shader {
vec4 params[uMAX][4]; vec4 params[uMAX][4];
enum Type : GLint { enum Type : GLint {
NONE = 0, DEFAULT = 0,
/* shader */ SPRITE = 0, FLASH = 1, ROOM = 2, ENTITY = 3, MIRROR = 4, /* shader */ SPRITE = 0, FLASH = 1, ROOM = 2, ENTITY = 3, MIRROR = 4,
/* filter */ FILTER_DOWNSAMPLE = 0, /* filter */ FILTER_DOWNSAMPLE = 1,
/* water */ WATER_DROP = 0, WATER_STEP = 1, WATER_CAUSTICS = 2, WATER_MASK = 3, WATER_COMPOSE = 4, /* water */ WATER_DROP = 0, WATER_STEP = 1, WATER_CAUSTICS = 2, WATER_MASK = 3, WATER_COMPOSE = 4,
MAX = 5 MAX = 5
}; };

View File

@@ -66,13 +66,12 @@ struct UI {
} }
void update() { void update() {
if (touch[zMove] != ikNone || touch[zLook] != ikNone || touch[zButton] != ikNone) {
touchTimerVis = 30.0f;
if (touchTimerTap > 0.0f) if (touchTimerTap > 0.0f)
touchTimerTap = max(0.0f, touchTimerTap - Core::deltaTime); touchTimerTap = max(0.0f, touchTimerTap - Core::deltaTime);
} else if (touch[zMove] != ikNone || touch[zLook] != ikNone || touch[zButton] != ikNone)
touchTimerVis = 30.0f;
else
if (touchTimerVis > 0.0f) if (touchTimerVis > 0.0f)
touchTimerVis = max(0.0f, touchTimerVis - Core::deltaTime); touchTimerVis = max(0.0f, touchTimerVis - Core::deltaTime);
@@ -116,11 +115,11 @@ struct UI {
if (t == ikNone) { if (t == ikNone) {
t = key; t = key;
if (zone == zMove) { if (zone == zMove) {
if (touchTimerTap > 0.0f && touchTimerTap < 0.4f) { // 100 ms gap to reduce false positives (bad touch sensors) if (touchTimerTap > 0.0f && touchTimerTap < 0.3f) { // 100 ms gap to reduce false positives (bad touch sensors)
doubleTap = true; doubleTap = true;
touchTimerTap = 0.0f; touchTimerTap = 0.0f;
} else } else
touchTimerTap = 0.5f; touchTimerTap = 0.3f;
} }
} }
} }
@@ -151,7 +150,7 @@ struct UI {
Core::mViewProj = mat4(0.0f, float(Core::width), float(Core::height), 0.0f, 0.0f, 1.0f); Core::mViewProj = mat4(0.0f, float(Core::width), float(Core::height), 0.0f, 0.0f, 1.0f);
game->setShader(Core::passGUI, Shader::NONE); game->setShader(Core::passGUI, Shader::DEFAULT);
float offset = Core::height * 0.25f; float offset = Core::height * 0.25f;