diff --git a/src/cache.h b/src/cache.h index a1ace88..5d13502 100644 --- a/src/cache.h +++ b/src/cache.h @@ -830,6 +830,7 @@ struct WaterCache { Core::setColorWrite(false, false, false, true); Core::setDepthWrite(false); Core::setCullMode(cmNone); + Core::setBlendMode(bmNone); for (int i = 0; i < count; i++) { Item &item = items[i]; @@ -894,7 +895,7 @@ struct WaterCache { Core::noiseTex->bind(sDiffuse); item.mask->bind(sMask); // add water drops - drop(item); + drop(item); // simulation step step(item); } @@ -1037,16 +1038,17 @@ struct WaterCache { vertices[1].light = vertices[2].light = vertices[3].light = ubyte4(255, 255, 255, 255); - vertices[0].texCoord = short4( 0, 32767, 0, 0); - vertices[1].texCoord = short4(32767, 32767, 0, 0); - vertices[2].texCoord = short4(32767, 0, 0, 0); - vertices[3].texCoord = short4( 0, 0, 0, 0); #if defined(_GAPI_D3D9) || defined(_GAPI_GXM) vertices[0].texCoord = short4( 0, 0, 0, 0); vertices[1].texCoord = short4(32767, 0, 0, 0); vertices[2].texCoord = short4(32767, 32767, 0, 0); vertices[3].texCoord = short4( 0, 32767, 0, 0); +#else + vertices[0].texCoord = short4( 0, 32767, 0, 0); + vertices[1].texCoord = short4(32767, 32767, 0, 0); + vertices[2].texCoord = short4(32767, 0, 0, 0); + vertices[3].texCoord = short4( 0, 0, 0, 0); #endif Core::setDepthTest(false); diff --git a/src/core.h b/src/core.h index 6920886..f9ea2f0 100644 --- a/src/core.h +++ b/src/core.h @@ -116,43 +116,6 @@ extern void osJoyVibrate (int index, float L, float R); #define OS_LOCK(mutex) Core::Lock _lock(mutex) -/* -extern void* osRWLockInit (); -extern void osRWLockFree (void *obj); -extern void osRWLockRead (void *obj); -extern void osRWUnlockRead (void *obj); -extern void osRWLockWrite (void *obj); -extern void osRWUnlockWrite (void *obj); - -struct RWLock { - void *obj; - - RWLock() { obj = osRWLockInit(); } - ~RWLock() { osRWLockFree(obj); } - void lockRead() { osRWLockRead(obj); } - void unlockRead() { osRWUnlockRead(obj); } - void lockWrite() { osRWLockWrite(obj); } - void unlockWrite() { osRWUnlockWrite(obj); } -}; - -struct LockRead { - RWLock &lock; - - LockRead(RWLock &lock) : lock(lock) { lock.lockRead(); } - ~LockRead() { lock.unlockRead(); } -}; - -struct LockWrite { - RWLock &lock; - - LockWrite(RWLock &lock) : lock(lock) { lock.lockWrite(); } - ~LockWrite() { lock.unlockWrite(); } -}; - -#define OS_LOCK_READ(rwLock) LockRead _rLock(rwLock) -#define OS_LOCK_WRITE(rwLock) LockWrite _wLock(rwLock) -*/ - enum InputKey { ikNone, // keyboard ikLeft, ikRight, ikUp, ikDown, ikSpace, ikTab, ikEnter, ikEscape, ikShift, ikCtrl, ikAlt, diff --git a/src/gapi_d3d9.h b/src/gapi_d3d9.h index 70e6cfb..2711ad1 100644 --- a/src/gapi_d3d9.h +++ b/src/gapi_d3d9.h @@ -50,14 +50,32 @@ void D3DCHECK(HRESULT res) { #endif namespace GAPI { - #include "shaders/d3d9/compose_vs.h" - #include "shaders/d3d9/compose_ps.h" + #include "shaders/d3d9/compose_sprite_vs.h" + #include "shaders/d3d9/compose_sprite_ps.h" + #include "shaders/d3d9/compose_flash_vs.h" + #include "shaders/d3d9/compose_flash_ps.h" + #include "shaders/d3d9/compose_room_vs.h" + #include "shaders/d3d9/compose_room_ps.h" + #include "shaders/d3d9/compose_entity_vs.h" + #include "shaders/d3d9/compose_entity_ps.h" + #include "shaders/d3d9/compose_mirror_vs.h" + #include "shaders/d3d9/compose_mirror_ps.h" #include "shaders/d3d9/shadow_vs.h" #include "shaders/d3d9/shadow_ps.h" #include "shaders/d3d9/ambient_vs.h" #include "shaders/d3d9/ambient_ps.h" - #include "shaders/d3d9/water_vs.h" - #include "shaders/d3d9/water_ps.h" + #include "shaders/d3d9/water_drop_vs.h" + #include "shaders/d3d9/water_drop_ps.h" + #include "shaders/d3d9/water_simulate_vs.h" + #include "shaders/d3d9/water_simulate_ps.h" + #include "shaders/d3d9/water_caustics_vs.h" + #include "shaders/d3d9/water_caustics_ps.h" + #include "shaders/d3d9/water_rays_vs.h" + #include "shaders/d3d9/water_rays_ps.h" + #include "shaders/d3d9/water_mask_vs.h" + #include "shaders/d3d9/water_mask_ps.h" + #include "shaders/d3d9/water_compose_vs.h" + #include "shaders/d3d9/water_compose_ps.h" #include "shaders/d3d9/filter_vs.h" #include "shaders/d3d9/filter_ps.h" #include "shaders/d3d9/gui_vs.h" @@ -141,10 +159,29 @@ namespace GAPI { void init(Core::Pass pass, int type, int *def, int defCount) { const BYTE *vSrc, *pSrc; switch (pass) { - case Core::passCompose : vSrc = COMPOSE_VS; pSrc = COMPOSE_PS; break; + case Core::passCompose : + switch (type) { + case 0 : vSrc = COMPOSE_SPRITE_VS; pSrc = COMPOSE_SPRITE_PS; break; + case 1 : vSrc = COMPOSE_FLASH_VS; pSrc = COMPOSE_FLASH_PS; break; + case 2 : vSrc = COMPOSE_ROOM_VS; pSrc = COMPOSE_ROOM_PS; break; + case 3 : vSrc = COMPOSE_ENTITY_VS; pSrc = COMPOSE_ENTITY_PS; break; + case 4 : vSrc = COMPOSE_MIRROR_VS; pSrc = COMPOSE_MIRROR_PS; break; + default : ASSERT(false); + } + break; case Core::passShadow : vSrc = SHADOW_VS; pSrc = SHADOW_PS; break; case Core::passAmbient : vSrc = AMBIENT_VS; pSrc = AMBIENT_PS; break; - case Core::passWater : vSrc = WATER_VS; pSrc = WATER_PS; break; + case Core::passWater : + switch (type) { + case 0 : vSrc = WATER_DROP_VS; pSrc = WATER_DROP_PS; break; + case 1 : vSrc = WATER_SIMULATE_VS; pSrc = WATER_SIMULATE_PS; break; + case 2 : vSrc = WATER_CAUSTICS_VS; pSrc = WATER_CAUSTICS_PS; break; + case 3 : vSrc = WATER_RAYS_VS; pSrc = WATER_RAYS_PS; break; + case 4 : vSrc = WATER_MASK_VS; pSrc = WATER_MASK_PS; break; + case 5 : vSrc = WATER_COMPOSE_VS; pSrc = WATER_COMPOSE_PS; break; + default : ASSERT(false); + } + break; case Core::passFilter : vSrc = FILTER_VS; pSrc = FILTER_PS; break; case Core::passGUI : vSrc = GUI_VS; pSrc = GUI_PS; break; default : ASSERT(false); LOG("! wrong pass id\n"); return; @@ -227,14 +264,14 @@ namespace GAPI { int bpp; D3DFORMAT format; } formats[FMT_MAX] = { - { 8, D3DFMT_L8 }, - { 32, D3DFMT_A8R8G8B8 }, - { 16, D3DFMT_R5G6B5 }, - { 16, D3DFMT_A1R5G5B5 }, - { 128, D3DFMT_A32B32G32R32F }, - { 64, D3DFMT_A16B16G16R16F }, - { 16, D3DFMT_D16 }, - { 16, D3DFMT_D24X8 }, + { 8, D3DFMT_L8 }, + { 32, D3DFMT_A8R8G8B8 }, + { 16, D3DFMT_R5G6B5 }, + { 16, D3DFMT_A1R5G5B5 }, + { 64, D3DFMT_G32R32F }, + { 32, D3DFMT_G16R16F }, + { 16, D3DFMT_D16 }, + { 16, D3DFMT_D24X8 }, }; FormatDesc desc = formats[fmt]; @@ -253,7 +290,18 @@ namespace GAPI { if (data && !isTarget) { D3DLOCKED_RECT rect; D3DCHECK(tex2D->LockRect(0, &rect, NULL, 0)); - memcpy(rect.pBits, data, width * height * (desc.bpp / 8)); + if (width != origWidth || height != origHeight) { + memset(rect.pBits, 0, width * height * (desc.bpp / 8)); + uint8 *dst = (uint8*)rect.pBits; + uint8 *src = (uint8*)data; + for (int y = 0; y < origHeight; y++) { + memcpy(dst, src, origWidth * (desc.bpp / 8)); + src += origWidth * (desc.bpp / 8); + dst += width * (desc.bpp / 8); + } + } else { + memcpy(rect.pBits, data, width * height * (desc.bpp / 8)); + } D3DCHECK(tex2D->UnlockRect(0)); } } diff --git a/src/gapi_gu.h b/src/gapi_gu.h index fa262de..c685e09 100644 --- a/src/gapi_gu.h +++ b/src/gapi_gu.h @@ -57,7 +57,7 @@ namespace GAPI { delete[] memory; } - void swizzle(uint8* out, const uint8* in, uint32 width, uint32 height) { + void swizzle(uint8 *out, const uint8 *in, uint32 width, uint32 height) { int rowblocks = width / 16; for (int j = 0; j < height; j++) diff --git a/src/gapi_gxm.h b/src/gapi_gxm.h index b9d4701..11e6800 100644 --- a/src/gapi_gxm.h +++ b/src/gapi_gxm.h @@ -11,8 +11,6 @@ #define PROFILE_LABEL(id, name, label) #define PROFILE_TIMING(time) -#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) - #define DISPLAY_WIDTH 960 #define DISPLAY_HEIGHT 544 #define DISPLAY_STRIDE 1024 @@ -21,14 +19,32 @@ #define DISPLAY_PIXEL_FORMAT SCE_DISPLAY_PIXELFORMAT_A8B8G8R8 namespace GAPI { - #include "shaders/gxm/compose_vp.h" - #include "shaders/gxm/compose_fp.h" + #include "shaders/gxm/compose_sprite_vp.h" + #include "shaders/gxm/compose_sprite_fp.h" + #include "shaders/gxm/compose_flash_vp.h" + #include "shaders/gxm/compose_flash_fp.h" + #include "shaders/gxm/compose_room_vp.h" + #include "shaders/gxm/compose_room_fp.h" + #include "shaders/gxm/compose_entity_vp.h" + #include "shaders/gxm/compose_entity_fp.h" + #include "shaders/gxm/compose_mirror_vp.h" + #include "shaders/gxm/compose_mirror_fp.h" #include "shaders/gxm/shadow_vp.h" #include "shaders/gxm/shadow_fp.h" #include "shaders/gxm/ambient_vp.h" #include "shaders/gxm/ambient_fp.h" - #include "shaders/gxm/water_vp.h" - #include "shaders/gxm/water_fp.h" + #include "shaders/gxm/water_drop_vp.h" + #include "shaders/gxm/water_drop_fp.h" + #include "shaders/gxm/water_simulate_vp.h" + #include "shaders/gxm/water_simulate_fp.h" + #include "shaders/gxm/water_caustics_vp.h" + #include "shaders/gxm/water_caustics_fp.h" + #include "shaders/gxm/water_rays_vp.h" + #include "shaders/gxm/water_rays_fp.h" + #include "shaders/gxm/water_mask_vp.h" + #include "shaders/gxm/water_mask_fp.h" + #include "shaders/gxm/water_compose_vp.h" + #include "shaders/gxm/water_compose_fp.h" #include "shaders/gxm/filter_vp.h" #include "shaders/gxm/filter_fp.h" #include "shaders/gxm/gui_vp.h" @@ -197,6 +213,23 @@ namespace GAPI { sceKernelFreeMemBlock(uid); } + uint32 *SWIZZE_TABLE = NULL; + #define SWIZZLE(x, y) ((SWIZZE_TABLE[(x)] << 1) | (SWIZZE_TABLE[(y)])) + + void initSwizzleTable() { + SWIZZE_TABLE = new uint32[4096]; + uint32 value = 0; + for (int i = 0; i < 4096; i++) { + SWIZZE_TABLE[i] = value; + value += 0x2AAAAAAB; + value &= 0x55555555; + } + } + + void freeSwizzleTable() { + delete[] SWIZZE_TABLE; + } + void init() { void *vdmRingBuffer = allocGPU( SCE_KERNEL_MEMBLOCK_TYPE_USER_RW_UNCACHE, SCE_GXM_DEFAULT_VDM_RING_BUFFER_SIZE, @@ -229,6 +262,8 @@ namespace GAPI { params.fragmentUsseRingBufferOffset = offset; sceGxmCreateContext(¶ms, &gxmContext); + + initSwizzleTable(); } void deinit() { @@ -240,6 +275,7 @@ namespace GAPI { freeGPU(fragmentRingBufferUID); freeFragmentUSSE(fragmentUsseRingBufferUID); sceGxmDestroyContext(gxmContext); + freeSwizzleTable(); } void checkPendings() { @@ -251,6 +287,67 @@ namespace GAPI { i++; } } + + template + void swizzleTiles(T *dst, T *src, int width, int tilesX, int tilesY) { + int tileSize = width / tilesX; + int tileArea = SQR(tileSize); + + for (int j = 0; j < tilesY; j++) { + for (int i = 0; i < tilesX; i++) { + T *tilePtr = dst + ((tileArea * tilesX) * j) + (tileArea * i); + + for (int y = 0; y < tileSize; y++) { + T *ptr = src + (width * (tileSize * j)) + (tileSize * i) + width * y; + + for (int x = 0; x < tileSize; x++) + *(tilePtr + SWIZZLE(x, y)) = *ptr++; + } + } + } + } + + void swizzleImage(void *dst, void *src, int width, int height, int bpp) { + ASSERT(SWIZZLE_TABLE); + + int tilesX, tilesY; + + if (width > height) { + tilesX = width / height; + tilesY = 1; + } else { + tilesX = 1; + tilesY = height / width; + } + + switch (bpp) { + case 8 : swizzleTiles( (uint8*) dst, (uint8*) src, width, tilesX, tilesY ); break; + case 16 : swizzleTiles( (uint16*) dst, (uint16*) src, width, tilesX, tilesY ); break; + case 32 : swizzleTiles( (uint32*) dst, (uint32*) src, width, tilesX, tilesY ); break; + } + } + + #define TILE_SIZE 32 + + void tileImage(void *dst, void *src, int width, int height, int bpp) { + int tilesX = width / TILE_SIZE; + int tilesY = height / TILE_SIZE; + + uint8 *tilePtr = (uint8*)dst; + for (int y = 0; y < tilesY; y++) { + for (int x = 0; x < tilesX; x++) { + uint8 *ptr = (uint8*)src + (width * y + x) * TILE_SIZE * bpp / 8; + + for (int i = 0; i < TILE_SIZE; i++) { + memcpy(tilePtr, ptr, TILE_SIZE * bpp / 8); + ptr += width * bpp / 8; + tilePtr += TILE_SIZE * bpp / 8; + } + } + } + } + + #undef TILE_SIZE }; namespace SwapChain { @@ -398,6 +495,8 @@ namespace GAPI { vec4 cbMem[98 + MAX_CONTACTS]; int cbCount[uMAX]; + SceGxmOutputRegisterFormat outputFmt; + int colorMask, blendMode; int psoIndex; @@ -406,12 +505,33 @@ namespace GAPI { void init(Pass pass, int type, int *def, int defCount) { memset(pso, 0, sizeof(pso)); + outputFmt = SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4; + const uint8 *vpSrc, *fpSrc; switch (pass) { - case passCompose : vpSrc = COMPOSE_VP; fpSrc = COMPOSE_FP; break; + case passCompose : + switch (type) { + case 0 : vpSrc = COMPOSE_SPRITE_VP; fpSrc = COMPOSE_SPRITE_FP; break; + case 1 : vpSrc = COMPOSE_FLASH_VP; fpSrc = COMPOSE_FLASH_FP; break; + case 2 : vpSrc = COMPOSE_ROOM_VP; fpSrc = COMPOSE_ROOM_FP; break; + case 3 : vpSrc = COMPOSE_ENTITY_VP; fpSrc = COMPOSE_ENTITY_FP; break; + case 4 : vpSrc = COMPOSE_MIRROR_VP; fpSrc = COMPOSE_MIRROR_FP; break; + default : ASSERT(false); + } + break; case passShadow : vpSrc = SHADOW_VP; fpSrc = SHADOW_FP; break; case passAmbient : vpSrc = AMBIENT_VP; fpSrc = AMBIENT_FP; break; - case passWater : vpSrc = WATER_VP; fpSrc = WATER_FP; break; + case passWater : + switch (type) { + case 0 : vpSrc = WATER_DROP_VP; fpSrc = WATER_DROP_FP; outputFmt = SCE_GXM_OUTPUT_REGISTER_FORMAT_HALF2; break; + case 1 : vpSrc = WATER_SIMULATE_VP; fpSrc = WATER_SIMULATE_FP; outputFmt = SCE_GXM_OUTPUT_REGISTER_FORMAT_HALF2; break; + case 2 : vpSrc = WATER_CAUSTICS_VP; fpSrc = WATER_CAUSTICS_FP; break; + case 3 : vpSrc = WATER_RAYS_VP; fpSrc = WATER_RAYS_FP; break; + case 4 : vpSrc = WATER_MASK_VP; fpSrc = WATER_MASK_FP; break; + case 5 : vpSrc = WATER_COMPOSE_VP; fpSrc = WATER_COMPOSE_FP; break; + default : ASSERT(false); + } + break; case passFilter : vpSrc = FILTER_VP; fpSrc = FILTER_FP; break; case passGUI : vpSrc = GUI_VP; fpSrc = GUI_FP; break; case PASS_CLEAR : vpSrc = CLEAR_VP; fpSrc = CLEAR_FP; break; @@ -502,39 +622,17 @@ namespace GAPI { this->colorMask = colorMask; this->blendMode = blendMode; - SceGxmBlendInfo blendInfo; - blendInfo.colorMask = SceGxmColorMask(colorMask); - blendInfo.colorFunc = SCE_GXM_BLEND_FUNC_ADD; - blendInfo.alphaFunc = SCE_GXM_BLEND_FUNC_ADD; - blendInfo.alphaSrc = SCE_GXM_BLEND_FACTOR_ONE; - blendInfo.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO; - psoIndex = 0; switch (blendMode) { - case RS_BLEND_ALPHA : - psoIndex = bmAlpha; - blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; - blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - case RS_BLEND_ADD : - psoIndex = bmAdd; - blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_ONE; - blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ONE; - break; - case RS_BLEND_MULT : - psoIndex = bmMult; - blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_DST_COLOR; - blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ZERO; - break; - case RS_BLEND_PREMULT : - psoIndex = bmPremult; - blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_ONE; - blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; - break; - default : - psoIndex = bmNone; - blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_ONE; - blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ZERO; + case RS_BLEND_ALPHA : psoIndex = bmAlpha; break; + case RS_BLEND_ADD : psoIndex = bmAdd; break; + case RS_BLEND_MULT : psoIndex = bmMult; break; + case RS_BLEND_PREMULT : psoIndex = bmPremult; break; + default : psoIndex = bmNone; + } + + if (outputFmt != SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4) { + psoIndex = 0; } if (colorMask != SCE_GXM_COLOR_MASK_ALL) { @@ -544,13 +642,45 @@ namespace GAPI { PSO &p = pso[psoIndex]; if (!p.fp) { - sceGxmShaderPatcherRegisterProgram(shaderPatcher, fpPtr, &p.fpUID); - sceGxmShaderPatcherCreateFragmentProgram(shaderPatcher, p.fpUID, SCE_GXM_OUTPUT_REGISTER_FORMAT_UCHAR4, SCE_GXM_MULTISAMPLE_NONE, &blendInfo, vpPtr, &p.fp); + SceGxmBlendInfo blendInfo; + blendInfo.colorMask = SceGxmColorMask(colorMask); + blendInfo.colorFunc = SCE_GXM_BLEND_FUNC_ADD; + blendInfo.alphaFunc = SCE_GXM_BLEND_FUNC_ADD; + blendInfo.alphaSrc = SCE_GXM_BLEND_FACTOR_ONE; + blendInfo.alphaDst = SCE_GXM_BLEND_FACTOR_ZERO; + + switch (blendMode) { + case RS_BLEND_ALPHA : + blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_SRC_ALPHA; + blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + break; + case RS_BLEND_ADD : + blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_ONE; + blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ONE; + break; + case RS_BLEND_MULT : + blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_DST_COLOR; + blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ZERO; + break; + case RS_BLEND_PREMULT : + blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_ONE; + blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA; + break; + default : + blendInfo.colorSrc = SCE_GXM_BLEND_FACTOR_ONE; + blendInfo.colorDst = SCE_GXM_BLEND_FACTOR_ZERO; + } + createFP(p, &blendInfo); } rebind = true; } + void createFP(PSO &p, SceGxmBlendInfo *blendInfo) { + sceGxmShaderPatcherRegisterProgram(shaderPatcher, fpPtr, &p.fpUID); + sceGxmShaderPatcherCreateFragmentProgram(shaderPatcher, p.fpUID, outputFmt, SCE_GXM_MULTISAMPLE_NONE, blendInfo, vpPtr, &p.fp); + } + void bind() { if (active.shader != this) { active.shader = this; @@ -602,80 +732,99 @@ namespace GAPI { }; // Texture + static const struct FormatDesc { + uint32 bpp, textureFormat, targetFormat; + } formats[FMT_MAX] = { + { 8, SCE_GXM_TEXTURE_FORMAT_U8_1RRR , SCE_GXM_COLOR_FORMAT_U8_R }, // LUMINANCE + { 32, SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ABGR , SCE_GXM_COLOR_FORMAT_A8B8G8R8 }, // RGBA + { 16, SCE_GXM_TEXTURE_FORMAT_U5U6U5_BGR , SCE_GXM_COLOR_FORMAT_U5U6U5_BGR }, // RGB16 + { 16, SCE_GXM_TEXTURE_FORMAT_U1U5U5U5_ABGR , SCE_GXM_COLOR_FORMAT_U1U5U5U5_ABGR }, // RGBA16 + { 64, SCE_GXM_TEXTURE_FORMAT_F32F32_GR , SCE_GXM_COLOR_FORMAT_F32F32_GR }, // RG_FLOAT // not supported + { 32, SCE_GXM_TEXTURE_FORMAT_F16F16_GR , SCE_GXM_COLOR_FORMAT_F16F16_GR }, // RG_HALF + { 32, SCE_GXM_TEXTURE_FORMAT_F32M_R , SCE_GXM_DEPTH_STENCIL_FORMAT_DF32 }, // DEPTH + { 32, SCE_GXM_TEXTURE_FORMAT_F32M_R , SCE_GXM_DEPTH_STENCIL_FORMAT_DF32 }, // SHADOW + }; + struct Texture { SceGxmTexture ID; - void *data; + uint8 *data; SceUID uid; - int size; - int width, height, origWidth, origHeight; + int width, height, origWidth, origHeight, aWidth, aHeight; TexFormat fmt; uint32 opt; SceGxmColorSurface colorSurface; SceGxmRenderTarget *renderTarget; - SceUID depthBufferUID; - SceGxmDepthStencilSurface depthSurface; - void *depthBufferData; + SceUID depthBufferUID; + SceGxmDepthStencilSurface depthSurface; + void *depthBufferData; - - Texture(int width, int height, uint32 opt) : width(width), height(height), origWidth(width), origHeight(height), fmt(FMT_RGBA), opt(opt) {} + Texture(int width, int height, uint32 opt) : width(width), height(height), origWidth(width), origHeight(height), fmt(FMT_RGBA), opt(opt) { opt |= OPT_NEAREST; } void init(void *data) { ASSERT((opt & OPT_PROXY) == 0); - bool filter = (opt & OPT_NEAREST) == 0; - bool mipmaps = (opt & OPT_MIPMAPS) != 0; - bool cube = (opt & OPT_CUBEMAP) != 0; - bool isTarget = (opt & OPT_TARGET) != 0; - bool isShadow = fmt == FMT_SHADOW; - - static const struct FormatDesc { - uint32 bpp, textureFormat, targetFormat; - } formats[FMT_MAX] = { - { 8, SCE_GXM_TEXTURE_FORMAT_U8_1RRR , SCE_GXM_COLOR_FORMAT_U8_R }, // LUMINANCE - { 32, SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB , SCE_GXM_COLOR_FORMAT_A8R8G8B8 }, // RGBA - { 16, SCE_GXM_TEXTURE_FORMAT_U5U6U5_RGB , SCE_GXM_COLOR_FORMAT_U5U6U5_RGB }, // RGB16 - { 16, SCE_GXM_TEXTURE_FORMAT_U1U5U5U5_ARGB , SCE_GXM_COLOR_FORMAT_U1U5U5U5_ARGB }, // RGBA16 - { 32, SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB , SCE_GXM_COLOR_FORMAT_A8R8G8B8 }, // RGBA - { 32, SCE_GXM_TEXTURE_FORMAT_U8U8U8U8_ARGB , SCE_GXM_COLOR_FORMAT_A8R8G8B8 }, // RGBA -// { 64, SCE_GXM_TEXTURE_FORMAT_F16F16F16F16_ARGB , SCE_GXM_COLOR_FORMAT_F16F16F16F16_RGBA }, // RGBA_FLOAT // not supported -// { 64, SCE_GXM_TEXTURE_FORMAT_F16F16F16F16_ARGB , SCE_GXM_COLOR_FORMAT_F16F16F16F16_RGBA }, // RGBA_HALF - { 32, SCE_GXM_TEXTURE_FORMAT_F32M_R , SCE_GXM_DEPTH_STENCIL_FORMAT_DF32 }, // DEPTH - { 32, SCE_GXM_TEXTURE_FORMAT_F32M_R , SCE_GXM_DEPTH_STENCIL_FORMAT_DF32 }, // SHADOW - }; + bool filter = (opt & OPT_NEAREST) == 0; + bool mipmaps = (opt & OPT_MIPMAPS) != 0; + bool isCube = (opt & OPT_CUBEMAP) != 0; + bool isTarget = (opt & OPT_TARGET) != 0; + bool isShadow = fmt == FMT_SHADOW; + bool isTiled = isTarget || fmt == FMT_DEPTH || fmt == FMT_SHADOW; + bool isSwizzled = false;//!isTiled; FormatDesc desc = formats[fmt]; - if (data && !support.texNPOT && (width != origWidth || height != origHeight)) - data = NULL; - - uint32 aWidth = width; - uint32 aHeight = height; - - if (fmt == FMT_DEPTH || fmt == FMT_SHADOW) { - aWidth = ALIGN(aWidth, SCE_GXM_TILE_SIZEX); - aHeight = ALIGN(aHeight, SCE_GXM_TILE_SIZEY); + if (isSwizzled) { + aWidth = width = nextPow2(width); + aHeight = height = nextPow2(height); + } else if (isTiled) { + aWidth = ALIGN(width, SCE_GXM_TILE_SIZEX); + aHeight = ALIGN(height, SCE_GXM_TILE_SIZEY); + } else { + aWidth = ALIGN(width, 8); + aHeight = height; } - size = aWidth * aHeight * desc.bpp / 8 * (cube ? 6 : 1); + int size = aWidth * aHeight * desc.bpp / 8 * (isCube ? 6 : 1); SceGxmMemoryAttribFlags flags = isTarget ? SCE_GXM_MEMORY_ATTRIB_RW : SCE_GXM_MEMORY_ATTRIB_READ; - this->data = Context::allocGPU(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, size, flags, &uid); + this->data = (uint8*)Context::allocGPU(SCE_KERNEL_MEMBLOCK_TYPE_USER_CDRAM_RW, size, flags, &uid); if (data && this->data) { - memcpy(this->data, data, size); + if (isSwizzled || isTiled) { + if (aWidth != origWidth || aHeight != origHeight) { + uint8 *tmp = new uint8[aWidth * aHeight * desc.bpp / 8]; + swap(this->data, tmp); + updateData(data); + swap(this->data, tmp); + if (isSwizzled) { + Context::swizzleImage(this->data, tmp, aWidth, aHeight, desc.bpp); + } else { + Context::tileImage(this->data, tmp, aWidth, aHeight, desc.bpp); + } + delete[] tmp; + } else { + if (isSwizzled) { + Context::swizzleImage(this->data, data, aWidth, aHeight, desc.bpp); + } else { + Context::tileImage(this->data, data, aWidth, aHeight, desc.bpp); + } + } + } else { + updateData(data); + } } - if (fmt == FMT_DEPTH || fmt == FMT_SHADOW) { - sceGxmTextureInitTiled(&ID, this->data, SceGxmTextureFormat(desc.textureFormat), width, height, 1); + if (isCube) { + sceGxmTextureInitCube(&ID, this->data, SceGxmTextureFormat(desc.textureFormat), width, height, 0); + } else if (isSwizzled) { + sceGxmTextureInitSwizzled(&ID, this->data, SceGxmTextureFormat(desc.textureFormat), width, height, 0); + } else if (isTiled) { + sceGxmTextureInitTiled(&ID, this->data, SceGxmTextureFormat(desc.textureFormat), width, height, 0); } else { - if (cube) { - sceGxmTextureInitCube(&ID, this->data, SceGxmTextureFormat(desc.textureFormat), width, height, 1); - } else { - sceGxmTextureInitLinear(&ID, this->data, SceGxmTextureFormat(desc.textureFormat), width, height, 1); - } + sceGxmTextureInitLinear(&ID, this->data, SceGxmTextureFormat(desc.textureFormat), width, height, 0); } SceGxmTextureAddrMode addrMode; @@ -684,6 +833,7 @@ namespace GAPI { } else { addrMode = (isShadow && support.texBorder) ? SCE_GXM_TEXTURE_ADDR_CLAMP_FULL_BORDER : SCE_GXM_TEXTURE_ADDR_CLAMP; } + sceGxmTextureSetUAddrMode(&ID, addrMode); sceGxmTextureSetUAddrMode(&ID, addrMode); @@ -704,10 +854,10 @@ namespace GAPI { } else { sceGxmColorSurfaceInit(&colorSurface, SceGxmColorFormat(desc.targetFormat), - SCE_GXM_COLOR_SURFACE_LINEAR, + isSwizzled ? SCE_GXM_COLOR_SURFACE_SWIZZLED : (isTiled ? SCE_GXM_COLOR_SURFACE_TILED : SCE_GXM_COLOR_SURFACE_LINEAR), SCE_GXM_COLOR_SURFACE_SCALE_NONE, - SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, - width, height, width, this->data); + desc.bpp > 32 ? SCE_GXM_OUTPUT_REGISTER_SIZE_64BIT : SCE_GXM_OUTPUT_REGISTER_SIZE_32BIT, + aWidth, aHeight, aWidth, this->data); uint32 dsWidth = ALIGN(width, SCE_GXM_TILE_SIZEX); uint32 dsHeight = ALIGN(height, SCE_GXM_TILE_SIZEY); @@ -726,8 +876,8 @@ namespace GAPI { SceGxmRenderTargetParams params; memset(¶ms, 0, sizeof(params)); - params.width = width; - params.height = height; + params.width = aWidth; + params.height = aHeight; params.scenesPerFrame = 1; params.multisampleMode = SCE_GXM_MULTISAMPLE_NONE; params.driverMemBlock = -1; @@ -758,9 +908,26 @@ namespace GAPI { */ } + void updateData(void *data) { + FormatDesc desc = formats[fmt]; + + if (aWidth != origWidth || aHeight != origHeight) { + uint8 *dst = (uint8*)this->data; + uint8 *src = (uint8*)data; + for (int y = 0; y < origHeight; y++) { + memcpy(dst, src, origWidth * desc.bpp / 8); + src += origWidth * desc.bpp / 8; + dst += aWidth * desc.bpp / 8; + } + } else { + memcpy(this->data, data, aWidth * aHeight * desc.bpp / 8); + } + } + void update(void *data) { - if (!data) return; - memcpy(this->data, data, size); + if (data) { + updateData(data); + } } void bind(int sampler) { diff --git a/src/platform/psv/main.cpp b/src/platform/psv/main.cpp index 506a0ae..122a447 100644 --- a/src/platform/psv/main.cpp +++ b/src/platform/psv/main.cpp @@ -80,8 +80,8 @@ void inputUpdate() { vec2 stickL = vec2(float(pad.lx), float(pad.ly)) / 128.0f - 1.0f; vec2 stickR = vec2(float(pad.rx), float(pad.ry)) / 128.0f - 1.0f; - if (fabsf(stickL.x) < 0.2f && fabsf(stickL.y) < 0.2f) stickL = vec2(0.0f); - if (fabsf(stickR.x) < 0.2f && fabsf(stickR.y) < 0.2f) stickR = vec2(0.0f); + if (fabsf(stickL.x) < 0.3f && fabsf(stickL.y) < 0.3f) stickL = vec2(0.0f); + if (fabsf(stickR.x) < 0.3f && fabsf(stickR.y) < 0.3f) stickR = vec2(0.0f); Input::setJoyPos(0, jkL, stickL); Input::setJoyPos(0, jkR, stickR); @@ -193,7 +193,8 @@ int main() { osTimerFreq = sceRtcGetTickResolution(); osStartTime = osGetTime(); - Game::init(); + Game::init("PSXDATA/LEVEL2.PSX"); +// sceRazorGpuCaptureSetTrigger(100, "ux0:data/OpenLara/capture.sgx"); while (!Core::isQuit) { inputUpdate(); diff --git a/src/platform/win/main.cpp b/src/platform/win/main.cpp index 023a1d3..8742404 100644 --- a/src/platform/win/main.cpp +++ b/src/platform/win/main.cpp @@ -25,9 +25,9 @@ // hint to the driver to use discrete GPU extern "C" { // NVIDIA - __declspec(dllexport) int NvOptimusEnablement = 1; + __declspec(dllexport) int NvOptimusEnablement = 1; // AMD - __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; + __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1; } #ifdef VR_SUPPORT @@ -57,34 +57,6 @@ void osMutexUnlock(void *obj) { LeaveCriticalSection((CRITICAL_SECTION*)obj); } -/* -void* osRWLockInit() { - SRWLOCK *lock = new SRWLOCK(); - InitializeSRWLock(lock); - return lock; -} - -void osRWLockFree(void *obj) { - delete (SRWLOCK*)obj; -} - -void osRWLockRead(void *obj) { - AcquireSRWLockShared((SRWLOCK*)obj); -} - -void osRWUnlockRead(void *obj) { - ReleaseSRWLockShared((SRWLOCK*)obj); -} - -void osRWLockWrite(void *obj) { - AcquireSRWLockExclusive((SRWLOCK*)obj); -} - -void osRWUnlockWrite(void *obj) { - ReleaseSRWLockExclusive((SRWLOCK*)obj); -} -*/ - // timing int osStartTime = 0; diff --git a/src/shaders/common.hlsl b/src/shaders/common.hlsl index 959443c..51fa214 100644 --- a/src/shaders/common.hlsl +++ b/src/shaders/common.hlsl @@ -3,6 +3,7 @@ #pragma pack_matrix( column_major ) #endif +#define ALPHA_REF 0.5 #define MAX_LIGHTS 4 #define MAX_CONTACTS 15 #define WATER_FOG_DIST (1.0 / (6.0 * 1024.0)) @@ -20,11 +21,13 @@ static const float3 SHADOW_TEXEL = float3(1.0 / SHADOW_SIZE, 1.0 / SHADOW_SIZE, #define FLAGS_TYPE float4 #define RGBA(c) (c).rgba #define RGB(c) (c).rgb + #define F2_TEX2D(s,uv) h2tex2Dlod(s, float4(uv, 0, 0)) #else - #define FLAGS_REG b0 - #define FLAGS_TYPE bool4 - #define RGBA(c) (c).bgra - #define RGB(c) (c).bgr + #define FLAGS_REG b0 + #define FLAGS_TYPE bool4 + #define RGBA(c) (c).rgba + #define RGB(c) (c).rgb + #define F2_TEX2D(s,uv) tex2Dlod(s, float4(uv, 0, 0)).xy #endif struct VS_INPUT { @@ -65,19 +68,13 @@ float4 uContacts[MAX_CONTACTS] : register( c98 ); #define FILTER_BLUR uFlags[1].x #define FILTER_EQUIRECTANGULAR uFlags[1].y -#define WATER_DROP uFlags[0].x -#define WATER_SIMULATE uFlags[0].y -#define WATER_CAUSTICS uFlags[0].z -#define WATER_RAYS uFlags[0].w -#define WATER_MASK uFlags[1].x -#define WATER_COMPOSE uFlags[1].y - // options for compose, shadow, ambient passes #define TYPE_SPRITE uFlags[0].x #define TYPE_FLASH uFlags[0].y #define TYPE_ROOM uFlags[0].z #define TYPE_ENTITY uFlags[0].w #define TYPE_MIRROR uFlags[1].x + #define UNDERWATER uFlags[1].y #define ALPHA_TEST uFlags[1].z #define CLIP_PLANE uFlags[1].w @@ -109,4 +106,106 @@ float3 calcAmbient(float3 n) { return sqr.x * lerp(uAmbient[1].xyz, uAmbient[0].xyz, pos.x) + sqr.y * lerp(uAmbient[3].xyz, uAmbient[2].xyz, pos.y) + sqr.z * lerp(uAmbient[5].xyz, uAmbient[4].xyz, pos.z); -} \ No newline at end of file +} + +float calcSpecular(float3 normal, float3 viewVec, float3 lightVec, float intensity) { + float3 vv = normalize(viewVec); + float3 rv = reflect(-vv, normal); + float3 lv = normalize(lightVec); + return pow(max(0.0, dot(rv, lv)), 8.0) * intensity; +} + +float calcCaustics(float3 coord, float3 n) { + float2 cc = saturate((coord.xz - uRoomSize.xy) / uRoomSize.zw); + return tex2Dlod(sReflect, float4(cc.x, 1.0 - cc.y, 0, 0)).x * max(0.0, -n.y); +} + +float3 calcNormal(float2 tc, float base) { + float dx = F2_TEX2D(sNormal, float2(tc.x + uTexParam.x, tc.y)).x - base; + float dz = F2_TEX2D(sNormal, float2(tc.x, tc.y + uTexParam.y)).x - base; + return normalize( float3(dx, 64.0 / (1024.0 * 8.0), dz) ); +} + +void applyFogUW(inout float3 color, float3 coord, float waterFogDist) { + float dist; + if (uViewPos.y < uParam.y) + dist = abs((coord.y - uParam.y) / normalize(uViewPos.xyz - coord.xyz).y); + else + dist = length(uViewPos.xyz - coord.xyz); + float fog = saturate(1.0 / exp(dist * waterFogDist)); + dist += coord.y - uParam.y; + color.xyz *= lerp(float3(1.0, 1.0, 1.0), UNDERWATER_COLOR, clamp(dist * waterFogDist, 0.0, 2.0)); + color.xyz = lerp(UNDERWATER_COLOR * 0.2, color.xyz, fog); +} + +void applyFog(inout float3 color, float fogFactor) { + color.xyz = lerp(uFogParams.xyz, color.xyz, fogFactor); +} + +float SHADOW(float2 p) { + #ifdef SHADOW_DEPTH + return tex2Dlod(sShadow, float4(p, 0, 0)).x; + #else + return unpack(tex2Dlod(sShadow, float4(p, 0, 0))); + #endif +} + +float getShadowValue(float3 lightVec, float4 lightProj) { +/* + float sMin = min(lightProj.x, lightProj.y); + float sMax = max(lightProj.x, lightProj.y); + float vis = lightProj.w; + if (TYPE_ROOM) { + vis = min(vis, dot(normal, lightVec)); + } + sMin = min(vis, sMin); +*/ + float factor = step(0.0, lightProj.w); //float((sMin > 0.0f) && (sMax < lightProj.w)); // + lightProj.xyz *= factor; + +#ifdef _GAPI_GXM + lightProj.z += SHADOW_CONST_BIAS * SHADOW_TEXEL.x * lightProj.w; + float rShadow = f1tex2Dproj(sShadow, lightProj); +#else + float3 p = lightProj.xyz / lightProj.w; + + p.z -= SHADOW_CONST_BIAS * SHADOW_TEXEL.x; + + p.z = saturate(p.z); + + float4 samples = float4( + SHADOW(p.xy ), + SHADOW(p.xy + SHADOW_TEXEL.xz), + SHADOW(p.xy + SHADOW_TEXEL.zy), + SHADOW(p.xy + SHADOW_TEXEL.xy) + ); + samples = step(p.zzzz, samples); + + float2 f = frac(p.xy / SHADOW_TEXEL.xy); + samples.xy = lerp(samples.xz, samples.yw, f.xx); + float rShadow = lerp(samples.x, samples.y, f.y); +#endif + + //rShadow = lerp(1.0, rShadow, factor); + + float fade = saturate(dot(lightVec, lightVec)); + return rShadow + (1.0 - rShadow) * fade; +} + +float getShadow(float3 lightVec, float3 normal, float4 lightProj) { + float factor = clamp(1.0 - dot(normalize(lightVec), normal), 0.0, 1.0); + factor *= SHADOW_NORMAL_BIAS; + return getShadowValue(lightVec, lightProj /*mul(uLightProj, float4(coord + normal * factor, 1.0)) */ ); +} + +float getContactAO(float3 p, float3 n) { + float res = 1.0; + #pragma loop (unroll: always) + for (int i = 0; i < MAX_CONTACTS; i++) { + float3 v = uContacts[i].xyz - p; + float a = uContacts[i].w; + float o = a * saturate(dot(n, v)) / dot(v, v); + res *= saturate(1.0 - o); + } + return res; +} diff --git a/src/shaders/compile_d3d9.bat b/src/shaders/compile_d3d9.bat index 7bcd548..a686dcc 100644 --- a/src/shaders/compile_d3d9.bat +++ b/src/shaders/compile_d3d9.bat @@ -1,14 +1,35 @@ @echo off rd /S /Q d3d9 mkdir d3d9 -fxc /nologo /T vs_3_0 /O3 /Gec /Vn COMPOSE_VS /Fh d3d9/compose_vs.h compose.hlsl /DPASS_COMPOSE /DVERTEX -fxc /nologo /T ps_3_0 /O3 /Gec /Vn COMPOSE_PS /Fh d3d9/compose_ps.h compose.hlsl /DPASS_COMPOSE /DPIXEL -fxc /nologo /T vs_3_0 /O3 /Gec /Vn SHADOW_VS /Fh d3d9/shadow_vs.h shadow.hlsl /DPASS_SHADOW /DVERTEX -fxc /nologo /T ps_3_0 /O3 /Gec /Vn SHADOW_PS /Fh d3d9/shadow_ps.h shadow.hlsl /DPASS_SHADOW /DPIXEL -fxc /nologo /T vs_3_0 /O3 /Gec /Vn AMBIENT_VS /Fh d3d9/ambient_vs.h ambient.hlsl /DPASS_AMBIENT /DVERTEX -fxc /nologo /T ps_3_0 /O3 /Gec /Vn AMBIENT_PS /Fh d3d9/ambient_ps.h ambient.hlsl /DPASS_AMBIENT /DPIXEL -fxc /nologo /T vs_3_0 /O3 /Gec /Vn WATER_VS /Fh d3d9/water_vs.h water.hlsl /DVERTEX -fxc /nologo /T ps_3_0 /O3 /Gec /Vn WATER_PS /Fh d3d9/water_ps.h water.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn COMPOSE_SPRITE_VS /Fh d3d9/compose_sprite_vs.h compose_sprite.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn COMPOSE_SPRITE_PS /Fh d3d9/compose_sprite_ps.h compose_sprite.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn COMPOSE_FLASH_VS /Fh d3d9/compose_flash_vs.h compose_flash.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn COMPOSE_FLASH_PS /Fh d3d9/compose_flash_ps.h compose_flash.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn COMPOSE_ROOM_VS /Fh d3d9/compose_room_vs.h compose_room.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn COMPOSE_ROOM_PS /Fh d3d9/compose_room_ps.h compose_room.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn COMPOSE_ENTITY_VS /Fh d3d9/compose_entity_vs.h compose_entity.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn COMPOSE_ENTITY_PS /Fh d3d9/compose_entity_ps.h compose_entity.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn COMPOSE_MIRROR_VS /Fh d3d9/compose_mirror_vs.h compose_mirror.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn COMPOSE_MIRROR_PS /Fh d3d9/compose_mirror_ps.h compose_mirror.hlsl /DPIXEL + +fxc /nologo /T vs_3_0 /O3 /Gec /Vn SHADOW_VS /Fh d3d9/shadow_vs.h shadow.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn SHADOW_PS /Fh d3d9/shadow_ps.h shadow.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn AMBIENT_VS /Fh d3d9/ambient_vs.h ambient.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn AMBIENT_PS /Fh d3d9/ambient_ps.h ambient.hlsl /DPIXEL + +fxc /nologo /T vs_3_0 /O3 /Gec /Vn WATER_DROP_VS /Fh d3d9/water_drop_vs.h water_drop.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn WATER_DROP_PS /Fh d3d9/water_drop_ps.h water_drop.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn WATER_SIMULATE_VS /Fh d3d9/water_simulate_vs.h water_simulate.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn WATER_SIMULATE_PS /Fh d3d9/water_simulate_ps.h water_simulate.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn WATER_CAUSTICS_VS /Fh d3d9/water_caustics_vs.h water_caustics.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn WATER_CAUSTICS_PS /Fh d3d9/water_caustics_ps.h water_caustics.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn WATER_RAYS_VS /Fh d3d9/water_rays_vs.h water_rays.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn WATER_RAYS_PS /Fh d3d9/water_rays_ps.h water_rays.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn WATER_MASK_VS /Fh d3d9/water_mask_vs.h water_mask.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn WATER_MASK_PS /Fh d3d9/water_mask_ps.h water_mask.hlsl /DPIXEL +fxc /nologo /T vs_3_0 /O3 /Gec /Vn WATER_COMPOSE_VS /Fh d3d9/water_compose_vs.h water_compose.hlsl /DVERTEX +fxc /nologo /T ps_3_0 /O3 /Gec /Vn WATER_COMPOSE_PS /Fh d3d9/water_compose_ps.h water_compose.hlsl /DPIXEL + fxc /nologo /T vs_3_0 /O3 /Gec /Vn FILTER_VS /Fh d3d9/filter_vs.h filter.hlsl /DVERTEX fxc /nologo /T ps_3_0 /O3 /Gec /Vn FILTER_PS /Fh d3d9/filter_ps.h filter.hlsl /DPIXEL fxc /nologo /T vs_3_0 /O3 /Gec /Vn GUI_VS /Fh d3d9/gui_vs.h gui.hlsl /DVERTEX diff --git a/src/shaders/compile_gxm.bat b/src/shaders/compile_gxm.bat index 13b1282..9d56b61 100644 --- a/src/shaders/compile_gxm.bat +++ b/src/shaders/compile_gxm.bat @@ -1,14 +1,37 @@ @echo off rd /S /Q gxm mkdir gxm -psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/compose_vp.gxp compose.hlsl -DPASS_COMPOSE -DVERTEX -psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/compose_fp.gxp compose.hlsl -DPASS_COMPOSE -DPIXEL -psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/shadow_vp.gxp shadow.hlsl -DPASS_SHADOW -DVERTEX -psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/shadow_fp.gxp shadow.hlsl -DPASS_SHADOW -DPIXEL -psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/ambient_vp.gxp ambient.hlsl -DPASS_AMBIENT -DVERTEX -psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/ambient_fp.gxp ambient.hlsl -DPASS_AMBIENT -DPIXEL -psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/water_vp.gxp water.hlsl -DVERTEX -psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/water_fp.gxp water.hlsl -DPIXEL + +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/compose_sprite_vp.gxp compose_sprite.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/compose_sprite_fp.gxp compose_sprite.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/compose_flash_vp.gxp compose_flash.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/compose_flash_fp.gxp compose_flash.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/compose_room_vp.gxp compose_room.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/compose_room_fp.gxp compose_room.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/compose_entity_vp.gxp compose_entity.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/compose_entity_fp.gxp compose_entity.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/compose_mirror_vp.gxp compose_mirror.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/compose_mirror_fp.gxp compose_mirror.hlsl -DPIXEL + +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/shadow_vp.gxp shadow.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/shadow_fp.gxp shadow.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/ambient_vp.gxp ambient.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/ambient_fp.gxp ambient.hlsl -DPIXEL + +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/water_drop_vp.gxp water_drop.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/water_drop_fp.gxp water_drop.hlsl -DPIXE +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/water_simulate_vp.gxp water_simulate.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/water_simulate_fp.gxp water_simulate.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/water_caustics_vp.gxp water_caustics.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/water_caustics_fp.gxp water_caustics.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/water_rays_vp.gxp water_rays.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/water_rays_fp.gxp water_rays.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/water_mask_vp.gxp water_mask.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/water_mask_fp.gxp water_mask.hlsl -DPIXEL +psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/water_compose_vp.gxp water_compose.hlsl -DVERTEX +psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/water_compose_fp.gxp water_compose.hlsl -DPIXEL + + psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/filter_vp.gxp filter.hlsl -DVERTEX psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/filter_fp.gxp filter.hlsl -DPIXEL psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/gui_vp.gxp gui.hlsl -DVERTEX @@ -17,14 +40,35 @@ psp2cgc -profile sce_vp_psp2 -W4 -Wperf -pedantic -o gxm/clear_vp.gxp clear.hlsl psp2cgc -profile sce_fp_psp2 -W4 -Wperf -pedantic -o gxm/clear_fp.gxp clear.hlsl -DPIXEL cd gxm -..\bin2c.exe compose_vp.gxp compose_vp.h COMPOSE_VP -..\bin2c.exe compose_fp.gxp compose_fp.h COMPOSE_FP +..\bin2c.exe compose_sprite_vp.gxp compose_sprite_vp.h COMPOSE_SPRITE_VP +..\bin2c.exe compose_sprite_fp.gxp compose_sprite_fp.h COMPOSE_SPRITE_FP +..\bin2c.exe compose_flash_vp.gxp compose_flash_vp.h COMPOSE_FLASH_VP +..\bin2c.exe compose_flash_fp.gxp compose_flash_fp.h COMPOSE_FLASH_FP +..\bin2c.exe compose_room_vp.gxp compose_room_vp.h COMPOSE_ROOM_VP +..\bin2c.exe compose_room_fp.gxp compose_room_fp.h COMPOSE_ROOM_FP +..\bin2c.exe compose_entity_vp.gxp compose_entity_vp.h COMPOSE_ENTITY_VP +..\bin2c.exe compose_entity_fp.gxp compose_entity_fp.h COMPOSE_ENTITY_FP +..\bin2c.exe compose_mirror_vp.gxp compose_mirror_vp.h COMPOSE_MIRROR_VP +..\bin2c.exe compose_mirror_fp.gxp compose_mirror_fp.h COMPOSE_MIRROR_FP + ..\bin2c.exe shadow_vp.gxp shadow_vp.h SHADOW_VP ..\bin2c.exe shadow_fp.gxp shadow_fp.h SHADOW_FP ..\bin2c.exe ambient_vp.gxp ambient_vp.h AMBIENT_VP ..\bin2c.exe ambient_fp.gxp ambient_fp.h AMBIENT_FP -..\bin2c.exe water_vp.gxp water_vp.h WATER_VP -..\bin2c.exe water_fp.gxp water_fp.h WATER_FP + +..\bin2c.exe water_drop_vp.gxp water_drop_vp.h WATER_DROP_VP +..\bin2c.exe water_drop_fp.gxp water_drop_fp.h WATER_DROP_FP +..\bin2c.exe water_simulate_vp.gxp water_simulate_vp.h WATER_SIMULATE_VP +..\bin2c.exe water_simulate_fp.gxp water_simulate_fp.h WATER_SIMULATE_FP +..\bin2c.exe water_caustics_vp.gxp water_caustics_vp.h WATER_CAUSTICS_VP +..\bin2c.exe water_caustics_fp.gxp water_caustics_fp.h WATER_CAUSTICS_FP +..\bin2c.exe water_rays_vp.gxp water_rays_vp.h WATER_RAYS_VP +..\bin2c.exe water_rays_fp.gxp water_rays_fp.h WATER_RAYS_FP +..\bin2c.exe water_mask_vp.gxp water_mask_vp.h WATER_MASK_VP +..\bin2c.exe water_mask_fp.gxp water_mask_fp.h WATER_MASK_FP +..\bin2c.exe water_compose_vp.gxp water_compose_vp.h WATER_COMPOSE_VP +..\bin2c.exe water_compose_fp.gxp water_compose_fp.h WATER_COMPOSE_FP + ..\bin2c.exe filter_vp.gxp filter_vp.h FILTER_VP ..\bin2c.exe filter_fp.gxp filter_fp.h FILTER_FP ..\bin2c.exe gui_vp.gxp gui_vp.h GUI_VP diff --git a/src/shaders/compose.hlsl b/src/shaders/compose.hlsl deleted file mode 100644 index 8f47e4e..0000000 --- a/src/shaders/compose.hlsl +++ /dev/null @@ -1,332 +0,0 @@ -#include "common.hlsl" - -struct VS_OUTPUT { - float4 pos : POSITION; - float3 coord : TEXCOORD0; - float4 texCoord : TEXCOORD1; - float4 viewVec : TEXCOORD2; - float4 normal : TEXCOORD3; - float4 diffuse : TEXCOORD4; - float3 ambient : TEXCOORD5; - float3 lightMap : TEXCOORD6; - float4 light : TEXCOORD7; - float4 lightProj : TEXCOORD8; -#ifdef _GAPI_GXM - float clipDist : CLP0; -#endif -}; - -#ifdef VERTEX -VS_OUTPUT main(VS_INPUT In) { - VS_OUTPUT Out; - Out.ambient = 0.0; - Out.lightMap = 0.0; - Out.light = 0.0; - - int index = int(In.aCoord.w * 2.0); - float4 rBasisRot = uBasis[index]; - float4 rBasisPos = uBasis[index + 1]; - - Out.texCoord = In.aTexCoord * (1.0 / 32767.0); - - if (TYPE_SPRITE) { - Out.coord = mulBasis(rBasisRot, rBasisPos.xyz + In.aCoord.xyz, float3(In.aTexCoord.z, In.aTexCoord.w, 0.0)); - } else { - Out.coord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz); - Out.texCoord.xy *= Out.texCoord.zw; - } - - Out.viewVec = float4((uViewPos.xyz - Out.coord) * uFogParams.w, Out.coord.y * uParam.z); - - if (TYPE_SPRITE) { - Out.normal.xyz = normalize(Out.viewVec.xyz); - } else { - Out.normal.xyz = mulQuat(rBasisRot, normalize(In.aNormal.xyz)); - } - - float fog; - - if (!TYPE_FLASH) { - float3 lv0 = (uLightPos[0].xyz - Out.coord) * uLightColor[0].w; - float3 lv1 = (uLightPos[1].xyz - Out.coord) * uLightColor[1].w; - float3 lv2 = (uLightPos[2].xyz - Out.coord) * uLightColor[2].w; - float3 lv3 = (uLightPos[3].xyz - Out.coord) * uLightColor[3].w; - - float4 lum, att; - if (TYPE_ENTITY) { - lum.x = dot(Out.normal.xyz, normalize(lv0)); - att.x = dot(lv0, lv0); - if (OPT_AMBIENT) { - Out.ambient = calcAmbient(Out.normal.xyz); - } else { - Out.ambient = min(uMaterial.yyy, RGB(In.aLight)); - } - } else { - if (TYPE_SPRITE) { - lum.x = uMaterial.y; - } else { - lum.x = 1.0; - } - att.x = 0.0; - - Out.ambient = min(uMaterial.yyy, RGB(In.aLight)); - } - - float4 light; - lum.y = dot(Out.normal.xyz, normalize(lv1)); att.y = dot(lv1, lv1); - lum.z = dot(Out.normal.xyz, normalize(lv2)); att.z = dot(lv2, lv2); - lum.w = dot(Out.normal.xyz, normalize(lv3)); att.w = dot(lv3, lv3); - light = max((float4)0.0, lum) * max((float4)0.0, (float4)1.0 - att); - - if (UNDERWATER) { - light.x *= abs(sin(dot(Out.coord.xyz, 1.0 / 512.0) + uParam.x)) * 1.5 + 0.5; - - float d; - if (uViewPos.y < uParam.y) { - d = abs((Out.coord.y - uParam.y) / normalize(uViewPos.xyz - Out.coord.xyz).y); - } else { - d = length(uViewPos.xyz - Out.coord.xyz); - } - fog = d * WATER_FOG_DIST; - fog *= step(uParam.y, Out.coord.y); - Out.normal.w = fog; - } else { - fog = length(Out.viewVec.xyz); - Out.normal.w = saturate(1.0 / exp(fog)); - } - Out.normal.w = saturate(1.0 / exp(fog)); - - if (OPT_SHADOW) { - Out.light = light; - Out.lightMap = RGB(In.aLight) * light.x; - } else { - Out.light.xyz = uLightColor[1].xyz * light.y + uLightColor[2].xyz * light.z + uLightColor[3].xyz * light.w; - Out.light.w = 0.0; - - if (TYPE_ENTITY) { - Out.light.xyz += Out.ambient + uLightColor[0].xyz * light.x; - } else { - Out.light.xyz += RGB(In.aLight) * light.x; - } - } - } else - Out.normal.w = 1.0; - - if (TYPE_MIRROR) { - Out.diffuse = uMaterial; - } else { - Out.diffuse = float4(RGB(In.aColor) * (uMaterial.x * 1.8), 1.0); - - if (TYPE_FLASH) { - Out.diffuse.xyz += uMaterial.w; - } else { - Out.diffuse *= uMaterial.w; - } - - if (TYPE_SPRITE) { - Out.diffuse *= RGBA(In.aLight).a; - } - } - - Out.pos = mul(uViewProj, float4(Out.coord, rBasisPos.w)); - Out.lightProj = mul(uLightProj, float4(Out.coord, 1.0)); -/* - if (TYPE_ROOM) { - float3 lightVec = uLightPos[0].xyz - Out.coord; - if (dot(Out.normal.xyz, lightVec) < 0.0) { - Out.lightProj.w = -1.0; - } - } -*/ -#ifdef _GAPI_GXM - Out.clipDist = uParam.w - Out.viewVec.w; -#endif - - return Out; -} - -#else // PIXEL - -float SHADOW(float2 p) { - #ifdef SHADOW_DEPTH - return tex2Dlod(sShadow, float4(p, 0, 0)).x; - #else - return unpack(tex2Dlod(sShadow, float4(p, 0, 0))); - #endif -} - -float getShadow(float3 lightVec, float3 normal, float4 lightProj) { -/* - float sMin = min(lightProj.x, lightProj.y); - float sMax = max(lightProj.x, lightProj.y); - float vis = lightProj.w; - if (TYPE_ROOM) { - vis = min(vis, dot(normal, lightVec)); - } - sMin = min(vis, sMin); -*/ - float factor = step(0.0, lightProj.w); //float((sMin > 0.0f) && (sMax < lightProj.w)); // - lightProj.xyz *= factor; - -#ifdef _GAPI_GXM - lightProj.z += SHADOW_CONST_BIAS * SHADOW_TEXEL.x * lightProj.w; - float rShadow = f1tex2Dproj(sShadow, lightProj); -#else - float3 p = lightProj.xyz / lightProj.w; - - p.z -= SHADOW_CONST_BIAS * SHADOW_TEXEL.x; - - p.z = saturate(p.z); - - float4 samples = float4( - SHADOW(p.xy ), - SHADOW(p.xy + SHADOW_TEXEL.xz), - SHADOW(p.xy + SHADOW_TEXEL.zy), - SHADOW(p.xy + SHADOW_TEXEL.xy) - ); - samples = step(p.zzzz, samples); - - float2 f = frac(p.xy / SHADOW_TEXEL.xy); - samples.xy = lerp(samples.xz, samples.yw, f.xx); - float rShadow = lerp(samples.x, samples.y, f.y); -#endif - - //rShadow = lerp(1.0, rShadow, factor); - - float fade = saturate(dot(lightVec, lightVec)); - return rShadow + (1.0 - rShadow) * fade; -} - -float getShadow(float3 coord, float3 lightVec, float3 normal, float4 lightProj) { - float factor = clamp(1.0 - dot(normalize(lightVec), normal), 0.0, 1.0); - factor *= SHADOW_NORMAL_BIAS; - return getShadow(lightVec, normal, lightProj /*mul(uLightProj, float4(coord + normal * factor, 1.0)) */ ); -} - -float getContactAO(float3 p, float3 n) { - float res = 1.0; - for (int i = 0; i < MAX_CONTACTS; i++) { - float3 v = uContacts[i].xyz - p; - float a = uContacts[i].w; - float o = a * saturate(dot(n, v)) / dot(v, v); - res *= saturate(1.0 - o); - } - return res; -} - -float calcCaustics(float3 coord, float3 n) { - float2 cc = saturate((coord.xz - uRoomSize.xy) / uRoomSize.zw); - return tex2Dlod(sReflect, float4(cc.x, 1.0 - cc.y, 0, 0)).x * max(0.0, -n.y); -} - -float calcSpecular(float3 normal, float3 viewVec, float3 lightVec, float intensity) { - float3 vv = normalize(viewVec); - float3 rv = reflect(-vv, normal); - float3 lv = normalize(lightVec); - return pow(max(0.0, dot(rv, lv)), 8.0) * intensity; -} - -float4 main(VS_OUTPUT In) : COLOR0 { - float2 uv = In.texCoord.xy; - - if (!TYPE_SPRITE) { - uv /= In.texCoord.zw; - } - - float4 color; - - if (TYPE_MIRROR) { - float3 rv = reflect(-normalize(In.viewVec.xyz), normalize(In.normal.xyz)); - color = texCUBE(sEnvironment, normalize(rv)).bgra; - } else { - color = tex2D(sDiffuse, uv).bgra; - - if (ALPHA_TEST) { - if (color.w <= 0.5) - discard; - } - } - -#ifndef _GAPI_GXM - if (CLIP_PLANE) { - if (In.viewVec.w > uParam.w) { - discard; - } - } -#endif - - color *= In.diffuse; - - if (TYPE_FLASH) { - return color; - } - - if (TYPE_MIRROR) { - return color; - } - - float3 lightVec = (uLightPos[0].xyz - In.coord) * uLightColor[0].w; - float3 normal = normalize(In.normal.xyz); - - float rSpecular = 0.0; - - float3 light; - if (OPT_SHADOW) { - light = uLightColor[1].xyz * In.light.y + uLightColor[2].xyz * In.light.z + uLightColor[3].xyz * In.light.w; - - if (TYPE_ENTITY) { - float rShadow = getShadow(In.coord, lightVec, normal, In.lightProj); - rSpecular = (uMaterial.z + 0.03) * rShadow; - light += In.ambient + uLightColor[0].xyz * (In.light.x * rShadow); - } else if (TYPE_ROOM) { - float rShadow = getShadow(In.coord, lightVec, normal, In.lightProj); - light += lerp(In.ambient, In.lightMap, rShadow); - } else if (TYPE_SPRITE) { - light += In.lightMap; - } - } else { - light = In.light.xyz; - } - - float uwSign = 1.0; - if (UNDERWATER) { - if (TYPE_ENTITY) { - uwSign = step(uParam.y, In.coord.y); - } - - if (OPT_CAUSTICS) { - light += calcCaustics(In.coord, normal); - } - } - - if (OPT_CONTACT) { - light *= getContactAO(In.coord, normal) * 0.5 + 0.5; - } - - color.xyz *= light; - - if (TYPE_ENTITY) { - float specular = calcSpecular(normal, In.viewVec.xyz, lightVec, rSpecular); - if (UNDERWATER) { - specular *= (1.0 - uwSign); - } - color.xyz += specular; - } - - if (UNDERWATER) { - float dist; - if (uViewPos.y < uParam.y) - dist = abs((In.coord.y - uParam.y) / normalize(uViewPos.xyz - In.coord.xyz).y); - else - dist = length(uViewPos.xyz - In.coord.xyz); - float fog = saturate(1.0 / exp(dist * WATER_FOG_DIST * uwSign)); - dist += In.coord.y - uParam.y; - color.xyz *= lerp(float3(1.0, 1.0, 1.0), UNDERWATER_COLOR, clamp(dist * WATER_COLOR_DIST * uwSign, 0.0, 2.0)); - color.xyz = lerp(UNDERWATER_COLOR * 0.2, color.xyz, fog); - } else { - color.xyz = lerp(uFogParams.xyz, color.xyz, In.normal.w); - } - - return color; -} -#endif \ No newline at end of file diff --git a/src/shaders/compose_entity.hlsl b/src/shaders/compose_entity.hlsl new file mode 100644 index 0000000..604d0de --- /dev/null +++ b/src/shaders/compose_entity.hlsl @@ -0,0 +1,144 @@ +#include "common.hlsl" + +// UNDERWATER, ALPHA_TEST, CLIP_PLANE (D3D9 only), OPT_SHADOW, OPT_CAUSTICS, OPT_AMBIENT + +struct VS_OUTPUT { + float4 pos : POSITION; + float3 coord : TEXCOORD0; + float4 texCoord : TEXCOORD1; + float4 viewVec : TEXCOORD2; + float4 normal : TEXCOORD3; + float4 diffuse : TEXCOORD4; + float3 ambient : TEXCOORD5; + float4 light : TEXCOORD6; + float4 lightProj : TEXCOORD7; +#ifdef _GAPI_GXM + float clipDist : CLP0; +#endif +}; + +#ifdef VERTEX +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + Out.ambient = 0.0; + + int index = int(In.aCoord.w * 2.0); + float4 rBasisRot = uBasis[index]; + float4 rBasisPos = uBasis[index + 1]; + + Out.texCoord = In.aTexCoord * (1.0 / 32767.0); + + Out.coord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz); + Out.texCoord.xy *= Out.texCoord.zw; + + Out.viewVec = float4((uViewPos.xyz - Out.coord) * uFogParams.w, uParam.w - Out.coord.y * uParam.z); + + Out.normal.xyz = mulQuat(rBasisRot, normalize(In.aNormal.xyz)); + + float3 lv0 = (uLightPos[0].xyz - Out.coord) * uLightColor[0].w; + float3 lv1 = (uLightPos[1].xyz - Out.coord) * uLightColor[1].w; + float3 lv2 = (uLightPos[2].xyz - Out.coord) * uLightColor[2].w; + float3 lv3 = (uLightPos[3].xyz - Out.coord) * uLightColor[3].w; + + if (OPT_AMBIENT) { + Out.ambient = calcAmbient(Out.normal.xyz); + } else { + Out.ambient = min(uMaterial.yyy, RGB(In.aLight)); + } + + float4 lum, att, light; + lum.x = dot(Out.normal.xyz, normalize(lv0)); att.x = dot(lv0, lv0); + lum.y = dot(Out.normal.xyz, normalize(lv1)); att.y = dot(lv1, lv1); + lum.z = dot(Out.normal.xyz, normalize(lv2)); att.z = dot(lv2, lv2); + lum.w = dot(Out.normal.xyz, normalize(lv3)); att.w = dot(lv3, lv3); + light = max((float4)0.0, lum) * max((float4)0.0, (float4)1.0 - att); + + if (UNDERWATER) { + light.x *= abs(sin(dot(Out.coord.xyz, 1.0 / 512.0) + uParam.x)) * 1.5 + 0.5; + Out.normal.w = 0.0; + } else { + Out.normal.w = saturate(1.0 / exp(length(Out.viewVec.xyz))); + } + + if (OPT_SHADOW) { + Out.light = light; + } else { + Out.light.xyz = uLightColor[1].xyz * light.y + uLightColor[2].xyz * light.z + uLightColor[3].xyz * light.w; + Out.light.w = 0.0; + + Out.light.xyz += Out.ambient + uLightColor[0].xyz * light.x; + } + + Out.diffuse = float4(RGB(In.aColor) * (uMaterial.x * 1.8), 1.0); + + Out.diffuse *= uMaterial.w; + + Out.pos = mul(uViewProj, float4(Out.coord, rBasisPos.w)); + Out.lightProj = mul(uLightProj, float4(Out.coord, 1.0)); + +#ifdef _GAPI_GXM + Out.clipDist = Out.viewVec.w; +#endif + + return Out; +} + +#else // PIXEL + +float4 main(VS_OUTPUT In) : COLOR0 { + float4 color = tex2D(sDiffuse, In.texCoord.xy / In.texCoord.zw); + + if (ALPHA_TEST) { + clip(color.w - ALPHA_REF); + } + +#ifndef _GAPI_GXM + if (CLIP_PLANE) { + clip(In.viewVec.w); + } +#endif + + color *= In.diffuse; + + float3 lightVec = (uLightPos[0].xyz - In.coord) * uLightColor[0].w; + float3 normal = normalize(In.normal.xyz); + + float rSpecular = 0.0; + + float3 light; + if (OPT_SHADOW) { + light = uLightColor[1].xyz * In.light.y + uLightColor[2].xyz * In.light.z + uLightColor[3].xyz * In.light.w; + float rShadow = getShadow(lightVec, normal, In.lightProj); + rSpecular = (uMaterial.z + 0.03) * rShadow; + light += In.ambient + uLightColor[0].xyz * (In.light.x * rShadow); + } else { + light = In.light.xyz; + } + + if (OPT_CAUSTICS) { + light += calcCaustics(In.coord, normal); + } + + if (OPT_CONTACT) { + light *= getContactAO(In.coord, normal) * 0.5 + 0.5; + } + + color.xyz *= light; + + float specular = calcSpecular(normal, In.viewVec.xyz, lightVec, rSpecular); + + if (UNDERWATER) { + float uwSign = step(uParam.y, In.coord.y); + specular *= (1.0 - uwSign); + color.xyz += specular; + + applyFogUW(color.xyz, In.coord, WATER_FOG_DIST * uwSign); + } else { + color.xyz += specular; + applyFog(color.xyz, In.normal.w); + } + + return color; +} + +#endif diff --git a/src/shaders/compose_flash.hlsl b/src/shaders/compose_flash.hlsl new file mode 100644 index 0000000..ef9c94b --- /dev/null +++ b/src/shaders/compose_flash.hlsl @@ -0,0 +1,51 @@ +#include "common.hlsl" + +// CLIP_PLANE (D3D9 only) + +struct VS_OUTPUT { + float4 pos : POSITION; + float4 texCoord : TEXCOORD0; + float3 diffuse : TEXCOORD1; +#ifdef _GAPI_GXM + float clipDist : CLP0; +#else + float clipDist : TEXCOORD2; +#endif +}; + +#ifdef VERTEX +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + int index = int(In.aCoord.w * 2.0); + float4 rBasisRot = uBasis[index]; + float4 rBasisPos = uBasis[index + 1]; + + float3 coord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz); + + Out.pos = mul(uViewProj, float4(coord, rBasisPos.w)); + Out.diffuse = In.aColor.rgb * (uMaterial.x * 1.8) + uMaterial.w; + Out.texCoord = In.aTexCoord * (1.0 / 32767.0); + Out.texCoord.xy *= Out.texCoord.zw; + + Out.clipDist = uParam.w - coord.y * uParam.z; + + return Out; +} + +#else // PIXEL + +float4 main(VS_OUTPUT In) : COLOR0 { + float4 color = tex2D(sDiffuse, In.texCoord.xy / In.texCoord.zw); + +#ifndef _GAPI_GXM + if (CLIP_PLANE) { + clip(In.clipDist); + } +#endif + + color.xyz *= In.diffuse.xyz; + return color; +} + +#endif diff --git a/src/shaders/compose_mirror.hlsl b/src/shaders/compose_mirror.hlsl new file mode 100644 index 0000000..21d3569 --- /dev/null +++ b/src/shaders/compose_mirror.hlsl @@ -0,0 +1,58 @@ +#include "common.hlsl" + +// CLIP_PLANE (D3D9 only) + +struct VS_OUTPUT { + float4 pos : POSITION; + float4 viewVec : TEXCOORD0; + float4 normal : TEXCOORD1; +#ifdef _GAPI_GXM + float clipDist : CLP0; +#endif +}; + +#ifdef VERTEX +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + int index = int(In.aCoord.w * 2.0); + float4 rBasisRot = uBasis[index]; + float4 rBasisPos = uBasis[index + 1]; + + float3 coord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz); + + Out.viewVec = float4((uViewPos.xyz - coord) * uFogParams.w, uParam.w - coord.y * uParam.z); + + Out.normal.xyz = mulQuat(rBasisRot, normalize(In.aNormal.xyz)); + Out.normal.w = saturate(1.0 / exp(length(Out.viewVec.xyz))); + + Out.pos = mul(uViewProj, float4(coord, rBasisPos.w)); + +#ifdef _GAPI_GXM + Out.clipDist = Out.viewVec.w; +#endif + + return Out; +} + +#else // PIXEL + +float4 main(VS_OUTPUT In) : COLOR0 { + float3 rv = reflect(-In.viewVec.xyz, In.normal.xyz); + float4 color = texCUBE(sEnvironment, normalize(rv)); + +#ifndef _GAPI_GXM + if (CLIP_PLANE) { + clip(In.viewVec.w); + } +#endif + + color *= uMaterial; + color.xyz = saturate(color.xyz); + + applyFog(color.xyz, In.normal.w); + + return color; +} + +#endif diff --git a/src/shaders/compose_room.hlsl b/src/shaders/compose_room.hlsl new file mode 100644 index 0000000..03b129a --- /dev/null +++ b/src/shaders/compose_room.hlsl @@ -0,0 +1,131 @@ +#include "common.hlsl" + +// UNDERWATER, ALPHA_TEST, CLIP_PLANE (D3D9 only), OPT_SHADOW, OPT_CAUSTICS, OPT_CONTACT + +struct VS_OUTPUT { + float4 pos : POSITION; + float3 coord : TEXCOORD0; + float4 texCoord : TEXCOORD1; + float4 normal : TEXCOORD2; + float4 diffuse : TEXCOORD3; + float3 ambient : TEXCOORD4; + float3 lightMap : TEXCOORD5; + float4 light : TEXCOORD6; + float4 lightProj : TEXCOORD7; +#ifdef _GAPI_GXM + float clipDist : CLP0; +#else + float clipDist : TEXCOORD8; +#endif +}; + +#ifdef VERTEX +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + float4 rBasisRot = uBasis[0]; + float4 rBasisPos = uBasis[1]; + + Out.texCoord = In.aTexCoord * (1.0 / 32767.0); + + Out.coord = mulBasis(rBasisRot, rBasisPos.xyz, In.aCoord.xyz); + Out.texCoord.xy *= Out.texCoord.zw; + + float3 viewVec = (uViewPos.xyz - Out.coord) * uFogParams.w; + + Out.normal.xyz = mulQuat(rBasisRot, normalize(In.aNormal.xyz)); + + float3 lv1 = (uLightPos[1].xyz - Out.coord) * uLightColor[1].w; + float3 lv2 = (uLightPos[2].xyz - Out.coord) * uLightColor[2].w; + float3 lv3 = (uLightPos[3].xyz - Out.coord) * uLightColor[3].w; + + float4 lum, att; + lum.x = 1.0; + att.x = 0.0; + + Out.ambient = min(uMaterial.yyy, In.aLight.rgb); + + float4 light; + lum.y = dot(Out.normal.xyz, normalize(lv1)); att.y = dot(lv1, lv1); + lum.z = dot(Out.normal.xyz, normalize(lv2)); att.z = dot(lv2, lv2); + lum.w = dot(Out.normal.xyz, normalize(lv3)); att.w = dot(lv3, lv3); + light = max((float4)0.0, lum) * max((float4)0.0, (float4)1.0 - att); + + if (UNDERWATER) { + light.x *= abs(sin(dot(Out.coord.xyz, 1.0 / 512.0) + uParam.x)) * 1.5 + 0.5; + Out.normal.w = 0.0; + } else { + Out.normal.w = saturate(1.0 / exp(length(viewVec.xyz))); + } + + if (OPT_SHADOW) { + Out.light = light; + Out.lightMap = In.aLight.rgb * light.x; + } else { + Out.light.xyz = uLightColor[1].xyz * light.y + uLightColor[2].xyz * light.z + uLightColor[3].xyz * light.w; + Out.light.w = 0.0; + Out.light.xyz += In.aLight.rgb * light.x; + Out.lightMap = 0.0; + } + + Out.diffuse = float4(In.aColor.rgb * (uMaterial.x * 1.8), 1.0); + + Out.diffuse *= uMaterial.w; + + Out.pos = mul(uViewProj, float4(Out.coord, rBasisPos.w)); + Out.lightProj = mul(uLightProj, float4(Out.coord, 1.0)); + + Out.clipDist = uParam.w - Out.coord.y * uParam.z; + + return Out; +} + +#else // PIXEL + +float4 main(VS_OUTPUT In) : COLOR0 { + float4 color = tex2D(sDiffuse, In.texCoord.xy / In.texCoord.zw); + + if (ALPHA_TEST) { + clip(color.w - ALPHA_REF); + } + +#ifndef _GAPI_GXM + if (CLIP_PLANE) { + clip(In.clipDist); + } +#endif + + color *= In.diffuse; + + float3 lightVec = (uLightPos[0].xyz - In.coord) * uLightColor[0].w; + float3 normal = normalize(In.normal.xyz); + + float3 light; + if (OPT_SHADOW) { + light = uLightColor[1].xyz * In.light.y + uLightColor[2].xyz * In.light.z + uLightColor[3].xyz * In.light.w; + float rShadow = getShadow(lightVec, normal, In.lightProj); + light += lerp(In.ambient, In.lightMap, rShadow); + } else { + light = In.light.xyz; + } + + if (OPT_CAUSTICS) { + light += calcCaustics(In.coord, normal); + } + + if (OPT_CONTACT) { + light *= getContactAO(In.coord, normal) * 0.5 + 0.5; + } + + color.xyz *= light; + + if (UNDERWATER) { + applyFogUW(color.xyz, In.coord, WATER_FOG_DIST); + } else { + applyFog(color.xyz, In.normal.w); + } + + return color; +} + +#endif diff --git a/src/shaders/compose_sprite.hlsl b/src/shaders/compose_sprite.hlsl new file mode 100644 index 0000000..a5dca2a --- /dev/null +++ b/src/shaders/compose_sprite.hlsl @@ -0,0 +1,107 @@ +#include "common.hlsl" + +// UNDERWATER, OPT_CAUSTICS, CLIP_PLANE (D3D9 only), ALPHA_TEST + +struct VS_OUTPUT { + float4 pos : POSITION; + float3 coord : TEXCOORD0; + float4 texCoord : TEXCOORD1; + float4 normal : TEXCOORD2; + float4 diffuse : TEXCOORD3; + float4 light : TEXCOORD4; +#ifdef _GAPI_GXM + float clipDist : CLP0; +#else + float clipDist : TEXCOORD5; +#endif +}; + +#ifdef VERTEX +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + float4 rBasisRot = uBasis[0]; + float4 rBasisPos = uBasis[1]; + + Out.texCoord = In.aTexCoord * (1.0 / 32767.0); + + Out.coord = mulBasis(rBasisRot, rBasisPos.xyz + In.aCoord.xyz, float3(In.aTexCoord.z, In.aTexCoord.w, 0.0)); + + float3 viewVec = (uViewPos.xyz - Out.coord) * uFogParams.w; + + Out.normal.xyz = normalize(viewVec); + + float3 lv1 = (uLightPos[1].xyz - Out.coord) * uLightColor[1].w; + float3 lv2 = (uLightPos[2].xyz - Out.coord) * uLightColor[2].w; + float3 lv3 = (uLightPos[3].xyz - Out.coord) * uLightColor[3].w; + + float4 lum, att; + lum.x = uMaterial.y; + att.x = 0.0; + + float4 light; + lum.y = dot(Out.normal.xyz, normalize(lv1)); att.y = dot(lv1, lv1); + lum.z = dot(Out.normal.xyz, normalize(lv2)); att.z = dot(lv2, lv2); + lum.w = dot(Out.normal.xyz, normalize(lv3)); att.w = dot(lv3, lv3); + light = max((float4)0.0, lum) * max((float4)0.0, (float4)1.0 - att); + + if (UNDERWATER) { + Out.normal.w = 0.0; + } else { + Out.normal.w = saturate(1.0 / exp(length(viewVec.xyz))); + } + + Out.light.xyz = uLightColor[1].xyz * light.y + uLightColor[2].xyz * light.z + uLightColor[3].xyz * light.w; + Out.light.w = 0.0; + + Out.light.xyz += In.aLight.rgb * light.x; + + Out.diffuse = float4(In.aColor.rgb * (uMaterial.x * 1.8), 1.0); + + Out.diffuse *= uMaterial.w; + Out.diffuse *= In.aLight.a; + + Out.pos = mul(uViewProj, float4(Out.coord, rBasisPos.w)); + + Out.clipDist = uParam.w - Out.coord.y * uParam.z; + + return Out; +} + +#else // PIXEL + +float4 main(VS_OUTPUT In) : COLOR0 { + float4 color = tex2D(sDiffuse, In.texCoord.xy); + + if (ALPHA_TEST) { + clip(color.w - ALPHA_REF); + } + +#ifndef _GAPI_GXM + if (CLIP_PLANE) { + clip(In.clipDist); + } +#endif + + color *= In.diffuse; + + float3 normal = normalize(In.normal.xyz); + + float3 light = In.light.xyz; + + if (OPT_CAUSTICS) { + light += calcCaustics(In.coord, normal); + } + + color.xyz *= light; + + if (UNDERWATER) { + applyFogUW(color.xyz, In.coord, WATER_FOG_DIST); + } else { + applyFog(color.xyz, In.normal.w); + } + + return color; +} + +#endif diff --git a/src/shaders/filter.hlsl b/src/shaders/filter.hlsl index e02b590..62612a9 100644 --- a/src/shaders/filter.hlsl +++ b/src/shaders/filter.hlsl @@ -46,7 +46,7 @@ float4 downsample(float2 uv) { // uParam (1 / textureSize, unused, unused, unuse float4 grayscale(float2 uv) { // uParam (factor, unused, unused, unused) float4 color = tex2D(sDiffuse, uv); float3 gray = dot(color, float4(0.299, 0.587, 0.114, 0.0)); - return float4(lerp(color.xyz, gray, uParam.w) * uParam.xyz, color.w).bgra; + return float4(lerp(color.xyz, gray, uParam.w) * uParam.xyz, color.w); } float4 blur(float2 uv) { // uParam (dirX, dirY, 1 / textureSize, unused) @@ -68,7 +68,7 @@ float4 upscale(float2 uv) { float2 fuv = frac(uv); uv = iuv + fuv * fuv * (3.0 - 2.0 * fuv); uv = (uv - 0.5) / uParam.xy; - return tex2D(sDiffuse, uv).bgra; + return tex2D(sDiffuse, uv); } float4 main(VS_OUTPUT In) : COLOR0 { diff --git a/src/shaders/gui.hlsl b/src/shaders/gui.hlsl index 9509758..23e061d 100644 --- a/src/shaders/gui.hlsl +++ b/src/shaders/gui.hlsl @@ -11,13 +11,13 @@ VS_OUTPUT main(VS_INPUT In) { VS_OUTPUT Out; Out.pos = mul(uViewProj, float4(In.aCoord.xy, 0.0, 1.0)); Out.texCoord = In.aTexCoord.xy * (1.0 / 32767.0); - Out.diffuse = RGBA(In.aLight) * uMaterial; + Out.diffuse = In.aLight * uMaterial; return Out; } #else // PIXEL float4 main(VS_OUTPUT In) : COLOR0 { - return In.diffuse * tex2D(sDiffuse, In.texCoord.xy).bgra; + return In.diffuse * tex2Dlod(sDiffuse, float4(In.texCoord, 0, 0)); } #endif \ No newline at end of file diff --git a/src/shaders/water.hlsl b/src/shaders/water.hlsl deleted file mode 100644 index 75eae48..0000000 --- a/src/shaders/water.hlsl +++ /dev/null @@ -1,251 +0,0 @@ -#include "common.hlsl" - -struct VS_OUTPUT { - float4 pos : POSITION; - float3 coord : TEXCOORD0; - float2 texCoord : TEXCOORD1; - float3 viewVec : TEXCOORD2; - float3 lightVec : TEXCOORD3; - float3 oldPos : TEXCOORD4; - float3 newPos : TEXCOORD5; - float4 hpos : TEXCOORD6; -}; - -float2 invUV(float2 uv) { - return float2(uv.x, 1.0 - uv.y); -} - -float3 getInvUV(float2 uv, float4 param) { - float2 p = (float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw; -#ifndef _GAPI_GXM - p.xy += 0.5 * param.xy; -#endif - return float3(p, 0.0); -} - -float2 getUV(float2 uv, float4 param) { - float2 p = (uv.xy * 0.5 + 0.5) * param.zw; -#ifndef _GAPI_GXM - //p.xy += 0.5 * param.xy; -#endif - return p; -} - -#ifdef VERTEX -VS_OUTPUT main(VS_INPUT In) { - VS_OUTPUT Out; - - Out.pos = 0.0; - Out.coord = 0.0; - Out.viewVec = 0.0; - Out.lightVec = 0.0; - Out.oldPos = 0.0; - Out.newPos = 0.0; - Out.hpos = 0.0; - - float3 coord = In.aCoord.xyz * (1.0 / 32767.0); - - Out.texCoord = getUV(coord.xy, uTexParam); - - if (WATER_COMPOSE) { - Out.coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz; - Out.pos = mul(uViewProj, float4(Out.coord, 1.0)); - Out.viewVec = uViewPos.xyz - Out.coord.xyz; - Out.lightVec = uLightPos[0].xyz - Out.coord.xyz; - Out.oldPos = getInvUV(coord.xy, uTexParam); - Out.texCoord = getUV(coord.xy, uRoomSize); - } else if (WATER_DROP) { - Out.pos = float4(coord.xyz, 1.0); - Out.oldPos = getInvUV(coord.xy, uTexParam); - } else if (WATER_SIMULATE) { - Out.pos = float4(coord.xyz, 1.0); - Out.oldPos = getInvUV(coord.xy, uTexParam); - Out.texCoord = getUV(coord.xy, uRoomSize); - } else if (WATER_CAUSTICS) { - float3 rCoord = float3(coord.x, coord.y, 0.0) * uPosScale[1].xzy; - float2 uv = getInvUV(rCoord.xy, uTexParam).xy; - float4 info = tex2Dlod(sNormal, float4(uv, 0, 0)); - float3 normal = float3(info.z, info.w, sqrt(1.0 - dot(info.zw, info.zw))); - - float3 light = float3(0.0, 0.0, 1.0); - float3 refOld = refract(-light, float3(0.0, 0.0, 1.0), 0.75); - float3 refNew = refract(-light, normal, 0.75); - - Out.oldPos = rCoord + refOld * (-1.0 / refOld.z) + refOld * ((-refOld.z - 1.0) / refOld.z); - Out.newPos = rCoord + refNew * ((info.r - 1.0) / refNew.z) + refOld * ((-refNew.z - 1.0) / refOld.z); - - Out.pos = float4(Out.newPos.xy + refOld.xy / refOld.z, 0.0, 1.0); - } else if (WATER_MASK) { - Out.coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz; - Out.pos = mul(uViewProj, float4(Out.coord, 1.0)); - } else if (WATER_RAYS) { - Out.coord = In.aCoord.xyz + uParam.xyz; - Out.viewVec = uViewPos.xyz - Out.coord.xyz; - Out.pos = mul(uViewProj, float4(Out.coord, 1.0)); - } - - Out.hpos = Out.pos; - - return Out; -} - -#else // PIXEL - -float calcFresnel(float VoH, float f0) { - float f = pow(1.0 - VoH, 5.0); - return f + f0 * (1.0f - f); -} - -float4 drop(VS_OUTPUT In) { - float2 iuv = In.oldPos.xy; - - float4 v = tex2D(sNormal, iuv); - - float value = max(0.0, 1.0 - length(uParam.xy - In.texCoord / uTexParam.xy) / uParam.z); - value = 0.5 - cos(value * PI) * 0.5; - - v.x += value * uParam.w; - - return v; -} - -float4 simulate(VS_OUTPUT In) { - float2 iuv = In.oldPos.xy; - float2 uv = In.texCoord; - - if (tex2D(sMask, uv).a < 0.5) - return 0.0; - - float4 v = tex2D(sNormal, iuv); // height, speed, normal.xz - - float3 d = float3(float2(uTexParam.x, -uTexParam.y), 0.0); - float4 f = float4( - tex2D(sNormal, iuv + d.xz).x, tex2D(sNormal, iuv + d.zy).x, - tex2D(sNormal, iuv - d.xz).x, tex2D(sNormal, iuv - d.zy).x - ); - - float average = dot(f, (float4)0.25); - -// normal - v.zw = normalize( float3(f.x - f.z, 64.0 / (1024.0 * 4.0), f.y - f.w) ).xz; - -// integrate - const float vel = 1.4; - const float vis = 0.995; - - v.y += (average - v.x) * vel; - v.y *= vis; - v.x += v.y + (tex2D(sDiffuse, uv + uParam.zw).x * 2.0 - 1.0) * 0.00025; - - return v; -} - -float4 caustics(VS_OUTPUT In) { - float rOldArea = length(ddx(In.oldPos)) * length(ddy(In.oldPos)); - float rNewArea = length(ddx(In.newPos)) * length(ddy(In.newPos)); - rNewArea = max(rNewArea, 0.00002); // WebGL NVIDIA workaround >_< - float value = saturate(rOldArea / rNewArea * 0.2); - return float4(value, 0.0, 0.0, 0.0); -} - -float boxIntersect(float3 rayPos, float3 rayDir, float3 center, float3 hsize) { - center -= rayPos; - float3 bMin = (center - hsize) / rayDir; - float3 bMax = (center + hsize) / rayDir; - float3 m = min(bMin, bMax); - return max(0.0, max(m.x, max(m.y, m.z))); -} - -float4 rays(VS_OUTPUT In, float2 pixelCoord) { - #define RAY_STEPS 16.0 - - float3 viewVec = normalize(In.viewVec); - - float t = boxIntersect(uViewPos.xyz, -viewVec, uPosScale[0].xyz, uPosScale[1].xyz); - - float3 p0 = uViewPos.xyz - viewVec * t; - float3 p1 = In.coord.xyz; - - float dither = tex2Dlod(sMask, float4(pixelCoord * (1.0 / 8.0), 0, 0)).x; - - float3 delta = (p1 - p0) / RAY_STEPS; - float3 pos = p0 + delta * dither; - - float sum = 0.0; - for (float i = 0.0; i < RAY_STEPS; i++) { - float3 wpos = (pos - uPosScale[0].xyz) / uPosScale[1].xyz; - float2 tc = wpos.xz * 0.5 + 0.5; - float light = tex2Dlod(sReflect, float4(tc, 0, 0)).x; - sum += light * (1.0 - (clamp(wpos.y, -1.0, 1.0) * 0.5 + 0.5)); - pos += delta; - } - sum /= RAY_STEPS; - sum *= uParam.w; - - return float4(UNDERWATER_COLOR * sum, 1.0); -} - -float4 mask() { - return 0.0; -} - -float4 compose(VS_OUTPUT In) { - float3 viewVec = normalize(In.viewVec); - float2 iuv = In.oldPos.xy; - - float4 value = tex2D(sNormal, iuv); - float3 normal = float3(value.z, sqrt(1.0 - dot(value.zw, value.zw)) * sign(viewVec.y), value.w); - float2 dudv = mul(uViewProj, float4(normal.x, 0.0, normal.z, 0.0)).xy; - - float3 rv = reflect(-viewVec, normal); - float3 lv = normalize(In.lightVec); - - float spec = pow(max(0.0, dot(rv, lv)), 64.0) * 0.5; - - float2 tc = In.hpos.xy / In.hpos.w * 0.5 + 0.5; - - float4 refrA = tex2D(sDiffuse, uParam.xy * invUV(clamp(tc + dudv * uParam.z, 0.0, 0.999)) ); - float4 refrB = tex2D(sDiffuse, uParam.xy * invUV(tc) ); - float4 refr = float4(lerp(refrA.xyz, refrB.xyz, refrA.w), 1.0); - float4 refl = tex2D(sReflect, tc.xy + dudv * uParam.w); - - float fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12); - - float4 color = lerp(refr, refl, fresnel) + spec * 1.5; - color.w *= tex2D(sMask, In.texCoord).a; - - float dist = In.viewVec.y / viewVec.y; - dist *= step(In.coord.y, uViewPos.y); - color.xyz *= lerp(float3(1.0, 1.0, 1.0), UNDERWATER_COLOR, clamp(dist * WATER_COLOR_DIST, 0.0, 2.0)); - float fog = saturate(1.0 / exp(dist * WATER_FOG_DIST)); - color.xyz = lerp(UNDERWATER_COLOR * 0.2, color.xyz, fog); - return color; -} - -#ifdef _GAPI_GXM -float4 main(VS_OUTPUT In) : COLOR0 { - float2 pixelCoord = float2(__pixel_x(), __pixel_y()); -#else -float4 main(VS_OUTPUT In, float4 pixelCoord: VPOS) : COLOR0 { -#endif - if (WATER_DROP) - return drop(In); - - if (WATER_SIMULATE) - return simulate(In); - - if (WATER_CAUSTICS) - return caustics(In); - - if (WATER_RAYS) - return rays(In, pixelCoord.xy); - - if (WATER_MASK) - return mask(); - - if (WATER_COMPOSE) - return compose(In); - - return float4(1.0, 0.0, 1.0, 1.0); -} -#endif \ No newline at end of file diff --git a/src/shaders/water_caustics.hlsl b/src/shaders/water_caustics.hlsl new file mode 100644 index 0000000..715d40f --- /dev/null +++ b/src/shaders/water_caustics.hlsl @@ -0,0 +1,58 @@ +#include "common.hlsl" + +struct VS_OUTPUT { + float4 pos : POSITION; + float2 texCoord : TEXCOORD0; + float3 oldPos : TEXCOORD1; + float3 newPos : TEXCOORD2; +}; + +float2 getInvUV(float2 uv, float4 param) { + float2 p = (float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw; +#ifndef _GAPI_GXM + p.xy += 0.5 * param.xy; +#endif + return p; +} + +float2 getUV(float2 uv, float4 param) { + return (uv.xy * 0.5 + 0.5) * param.zw; +} + +#ifdef VERTEX +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + float3 coord = In.aCoord.xyz * (1.0 / 32767.0); + + Out.texCoord = getUV(coord.xy, uTexParam); + + float3 rCoord = float3(coord.x, coord.y, 0.0) * uPosScale[1].xzy; + + float2 uv = getInvUV(rCoord.xy, uTexParam).xy; + float2 info = F2_TEX2D(sNormal, uv).xy; + float3 normal = calcNormal(uv, info.x).xzy; + + float3 light = float3(0.0, 0.0, 1.0); + float3 refOld = refract(-light, float3(0.0, 0.0, 1.0), 0.75); + float3 refNew = refract(-light, normal, 0.75); + + Out.oldPos = rCoord + refOld * (-1.0 / refOld.z) + refOld * ((-refOld.z - 1.0) / refOld.z); + Out.newPos = rCoord + refNew * ((info.r - 1.0) / refNew.z) + refOld * ((-refNew.z - 1.0) / refOld.z); + + Out.pos = float4(Out.newPos.xy + refOld.xy / refOld.z, 0.0, 1.0); + + return Out; +} + +#else // PIXEL + +float4 main(VS_OUTPUT In) : COLOR0 { + float rOldArea = length(ddx(In.oldPos)) * length(ddy(In.oldPos)); + float rNewArea = length(ddx(In.newPos)) * length(ddy(In.newPos)); + rNewArea = max(rNewArea, 0.00002); // WebGL NVIDIA workaround >_< + float value = saturate(rOldArea / rNewArea * 0.2); + return float4(value, 0.0, 0.0, 0.0); +} + +#endif diff --git a/src/shaders/water_compose.hlsl b/src/shaders/water_compose.hlsl new file mode 100644 index 0000000..e129310 --- /dev/null +++ b/src/shaders/water_compose.hlsl @@ -0,0 +1,88 @@ +#include "common.hlsl" + +struct VS_OUTPUT { + float4 pos : POSITION; + float3 coord : TEXCOORD0; + float2 texCoord : TEXCOORD1; + float2 maskCoord : TEXCOORD2; + float3 viewVec : TEXCOORD3; + float3 lightVec : TEXCOORD4; + float3 hpos : TEXCOORD5; +}; + +float2 invUV(float2 uv) { + return float2(uv.x, 1.0 - uv.y); +} + +float2 getInvUV(float2 uv, float4 param) { + float2 p = (float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw; +#ifndef _GAPI_GXM + p.xy += 0.5 * param.xy; +#endif + return p; +} + +float2 getUV(float2 uv, float4 param) { + return (uv.xy * 0.5 + 0.5) * param.zw; +} + +#ifdef VERTEX +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + float3 coord = In.aCoord.xyz * (1.0 / 32767.0); + + Out.coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz; + Out.pos = mul(uViewProj, float4(Out.coord, 1.0)); + Out.viewVec = uViewPos.xyz - Out.coord.xyz; + Out.lightVec = uLightPos[0].xyz - Out.coord.xyz; + Out.texCoord = getInvUV(coord.xy, uTexParam); + Out.maskCoord = getUV(coord.xy, uRoomSize); + Out.hpos = Out.pos.xyw; + + return Out; +} + +#else // PIXEL + +float calcFresnel(float VoH, float f0) { + float f = pow(1.0 - VoH, 5.0); + return f + f0 * (1.0f - f); +} + +float4 main(VS_OUTPUT In) : COLOR0 { + float3 viewVec = normalize(In.viewVec); + + float2 value = F2_TEX2D(sNormal, In.texCoord).xy; + + float3 normal = calcNormal(In.texCoord, value.x); + normal.y *= sign(viewVec.y); + + float2 dudv = mul(uViewProj, float4(normal.x, 0.0, normal.z, 0.0)).xy; + + float3 rv = reflect(-viewVec, normal); + float3 lv = normalize(In.lightVec); + + float spec = pow(max(0.0, dot(rv, lv)), 64.0) * 0.5; + + float2 tc = In.hpos.xy / In.hpos.z * 0.5 + 0.5; + + float4 refrA = tex2Dlod(sDiffuse, float4(uParam.xy * invUV(clamp(tc + dudv * uParam.z, 0.0, 0.999)), 0, 0) ); + float4 refrB = tex2Dlod(sDiffuse, float4(uParam.xy * invUV(tc), 0, 0) ); + float4 refr = float4(lerp(refrA.xyz, refrB.xyz, refrA.w), 1.0); + float4 refl = tex2Dlod(sReflect, float4(tc.xy + dudv * uParam.w, 0, 0)); + + float fresnel = calcFresnel(max(0.0, dot(normal, viewVec)), 0.12); + + float4 color = lerp(refr, refl, fresnel) + spec * 1.5; + color.w *= tex2Dlod(sMask, float4(In.maskCoord, 0, 0)).a; + + float dist = In.viewVec.y / viewVec.y; + dist *= step(In.coord.y, uViewPos.y); + color.xyz *= lerp(float3(1.0, 1.0, 1.0), UNDERWATER_COLOR, clamp(dist * WATER_COLOR_DIST, 0.0, 2.0)); + float fog = saturate(1.0 / exp(dist * WATER_FOG_DIST)); + color.xyz = lerp(UNDERWATER_COLOR * 0.2, color.xyz, fog); + return color; +} + +#endif diff --git a/src/shaders/water_drop.hlsl b/src/shaders/water_drop.hlsl new file mode 100644 index 0000000..2c87a9f --- /dev/null +++ b/src/shaders/water_drop.hlsl @@ -0,0 +1,51 @@ +#include "common.hlsl" + +struct VS_OUTPUT { + float4 pos : POSITION; + float2 texCoord : TEXCOORD0; + float2 dropCoord : TEXCOORD1; +}; + +float2 getInvUV(float2 uv, float4 param) { + float2 p = (float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw; +#ifndef _GAPI_GXM + p.xy += 0.5 * param.xy; +#endif + return p; +} + +float2 getUV(float2 uv, float4 param) { + float2 p = (uv.xy * 0.5 + 0.5) * param.zw; + return p; +} + +#ifdef VERTEX + +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + float3 coord = In.aCoord.xyz * (1.0 / 32767.0); + + Out.pos = float4(coord.xyz, 1.0); + Out.texCoord = getInvUV(coord.xy, uTexParam); + Out.dropCoord = getUV(coord.xy, uTexParam); + + return Out; +} + +#else // PIXEL + +half4 main(VS_OUTPUT In) : COLOR0 { + half2 v = (half2)tex2Dlod(sNormal, float4(In.texCoord.xy, 0, 0)).xy; + + float value = max(0.0, 1.0 - length(uParam.xy - In.dropCoord / uTexParam.xy) / uParam.z); + value = 0.5 - cos(value * PI) * 0.5; + value *= uParam.w; + + v.x += (half)value; + //v.x = 1.0; + + return half4(v, 0, 0); +} + +#endif diff --git a/src/shaders/water_mask.hlsl b/src/shaders/water_mask.hlsl new file mode 100644 index 0000000..d5eedac --- /dev/null +++ b/src/shaders/water_mask.hlsl @@ -0,0 +1,17 @@ +#include "common.hlsl" + +#ifdef VERTEX + +float4 main(VS_INPUT In) : POSITION { + float3 coord = In.aCoord.xyz * (1.0 / 32767.0); + coord = float3(coord.x, 0.0, coord.y) * uPosScale[1].xyz + uPosScale[0].xyz; + return mul(uViewProj, float4(coord, 1.0)); +} + +#else // PIXEL + +float4 main() : COLOR0 { + return 0.0; +} + +#endif diff --git a/src/shaders/water_rays.hlsl b/src/shaders/water_rays.hlsl new file mode 100644 index 0000000..76a8e18 --- /dev/null +++ b/src/shaders/water_rays.hlsl @@ -0,0 +1,65 @@ +#include "common.hlsl" + +#define RAY_STEPS 16.0 + +struct VS_OUTPUT { + float4 pos : POSITION; + float3 coord : TEXCOORD0; + float3 viewVec : TEXCOORD1; +}; + +#ifdef VERTEX + +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + Out.coord = In.aCoord.xyz + uParam.xyz; + Out.viewVec = uViewPos.xyz - Out.coord.xyz; + Out.pos = mul(uViewProj, float4(Out.coord, 1.0)); + + return Out; +} + +#else // PIXEL + +float boxIntersect(float3 rayPos, float3 rayDir, float3 center, float3 hsize) { + center -= rayPos; + float3 bMin = (center - hsize) / rayDir; + float3 bMax = (center + hsize) / rayDir; + float3 m = min(bMin, bMax); + return max(0.0, max(m.x, max(m.y, m.z))); +} + +#ifdef _GAPI_GXM +float4 main(VS_OUTPUT In) : COLOR0 { + float2 pixelCoord = float2(__pixel_x(), __pixel_y()); +#else +float4 main(VS_OUTPUT In, float2 pixelCoord: VPOS) : COLOR0 { +#endif + float3 viewVec = normalize(In.viewVec); + + float t = boxIntersect(uViewPos.xyz, -viewVec, uPosScale[0].xyz, uPosScale[1].xyz); + + float3 p0 = uViewPos.xyz - viewVec * t; + float3 p1 = In.coord.xyz; + + float dither = tex2Dlod(sMask, float4(pixelCoord * (1.0 / 8.0), 0.0, 0.0)).x; + + float3 delta = (p1 - p0) / RAY_STEPS; + float3 pos = p0 + delta * dither; + + float sum = 0.0; + for (float i = 0.0; i < RAY_STEPS; i++) { + float3 wpos = (pos - uPosScale[0].xyz) / uPosScale[1].xyz; + float2 tc = wpos.xz * 0.5 + 0.5; + float light = tex2Dlod(sReflect, float4(tc, 0, 0)).x; + sum += light * (1.0 - (clamp(wpos.y, -1.0, 1.0) * 0.5 + 0.5)); + pos += delta; + } + sum /= RAY_STEPS; + sum *= uParam.w; + + return float4(UNDERWATER_COLOR * sum, 1.0); +} + +#endif diff --git a/src/shaders/water_simulate.hlsl b/src/shaders/water_simulate.hlsl new file mode 100644 index 0000000..98bd623 --- /dev/null +++ b/src/shaders/water_simulate.hlsl @@ -0,0 +1,63 @@ +#include "common.hlsl" + +struct VS_OUTPUT { + float4 pos : POSITION; + float2 texCoord : TEXCOORD0; + float2 maskCoord : TEXCOORD1; +}; + +float2 getInvUV(float2 uv, float4 param) { + float2 p = (float2(uv.x, -uv.y) * 0.5 + 0.5) * param.zw; +#ifndef _GAPI_GXM + p.xy += 0.5 * param.xy; +#endif + return p; +} + +float2 getUV(float2 uv, float4 param) { + return (uv.xy * 0.5 + 0.5) * param.zw; +} + +#ifdef VERTEX +VS_OUTPUT main(VS_INPUT In) { + VS_OUTPUT Out; + + float3 coord = In.aCoord.xyz * (1.0 / 32767.0); + + Out.pos = float4(coord.xyz, 1.0); + Out.texCoord = getInvUV(coord.xy, uTexParam); + Out.maskCoord = getUV(coord.xy, uRoomSize); + + return Out; +} + +#else // PIXEL + +half4 main(VS_OUTPUT In) : COLOR0 { + float2 uv = In.texCoord.xy; + if (tex2Dlod(sMask, float4(In.maskCoord, 0, 0)).a < 0.5) + return 0.0; + + half2 v = (half2)tex2Dlod(sNormal, float4(uv, 0, 0)).xy; // height, speed + + float3 d = float3(float2(uTexParam.x, -uTexParam.y), 0.0); + float4 f = float4( + F2_TEX2D(sNormal, uv + d.xz).x, F2_TEX2D(sNormal, uv + d.zy).x, + F2_TEX2D(sNormal, uv - d.xz).x, F2_TEX2D(sNormal, uv - d.zy).x + ); + + float average = dot(f, (float4)0.25); + +// integrate + const half vel = 1.4; + const half vis = 0.995; + + v.y += (half)((average - v.x) * vel); + v.y *= vis; + v.x += v.y + (half)(tex2Dlod(sDiffuse, float4(uv + uParam.zw, 0, 0)).x * 2.0 - 1.0) * 0.00025; + + return half4(v, 0, 0); + +} + +#endif diff --git a/src/ui.h b/src/ui.h index 2872e15..e9ec2ea 100644 --- a/src/ui.h +++ b/src/ui.h @@ -6,7 +6,10 @@ #include "controller.h" #define PICKUP_SHOW_TIME 5.0f -//#define UI_SHOW_FPS + +#ifdef _OS_PSV + #define UI_SHOW_FPS +#endif enum StringID { STR_NOT_IMPLEMENTED diff --git a/src/utils.h b/src/utils.h index 09b865c..356ca36 100644 --- a/src/utils.h +++ b/src/utils.h @@ -96,6 +96,7 @@ typedef unsigned long long uint64; #define FOURCC(str) uint32(((uint8*)(str))[0] | (((uint8*)(str))[1] << 8) | (((uint8*)(str))[2] << 16) | (((uint8*)(str))[3] << 24) ) +#define ALIGN(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) #define COUNT(arr) int(sizeof(arr) / sizeof(arr[0])) #define OFFSETOF(T, E) ((size_t)&(((T*)0)->E)) #define TEST_BIT(arr, bit) ((arr[bit / 32] >> (bit % 32)) & 1) @@ -178,6 +179,12 @@ float hermite(float x) { return x * x * (3.0f - 2.0f * x); } +float lerpHermite(float a, float b, float t) { + if (t <= 0.0f) return a; + if (t >= 1.0f) return b; + return a + (b - a) * hermite(t); +} + float lerp(float a, float b, float t) { if (t <= 0.0f) return a; if (t >= 1.0f) return b;