postprocess render pass
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,95 @@
|
||||
#version 450
|
||||
|
||||
struct Material {
|
||||
vec3 albedo;
|
||||
float specular;
|
||||
};
|
||||
|
||||
// Variables
|
||||
layout(location=0) in vec2 _InUV;
|
||||
layout(location=0) out vec4 _OutColor;
|
||||
|
||||
layout(set=0,binding=0) uniform Uniforms {
|
||||
mat4 _ViewMatrix;
|
||||
mat4 _ProjMatrixInv;
|
||||
vec3 _CamPos;
|
||||
vec3 _SunDir;
|
||||
float _Time;
|
||||
};
|
||||
layout(set=1,binding=0) uniform usampler3D _NodesTexture;
|
||||
layout(set=2,binding=0) uniform usampler3D _BricksTexture;
|
||||
layout(set=3, binding=0) uniform Materials {
|
||||
Material _Materials[256];
|
||||
};
|
||||
|
||||
// Defines
|
||||
#define EPSILON 0.00000001
|
||||
#define SCALE 1.0
|
||||
#define NODE_TEX_SIZE 48
|
||||
#define BLOCK_TEX_SIZE 64
|
||||
#define BLOCK_SIZE 32
|
||||
|
||||
|
||||
// Include
|
||||
#include "structs.cginc"
|
||||
#include "shading.cginc"
|
||||
#include "raycasting.cginc"
|
||||
|
||||
|
||||
float seed;
|
||||
float random(float s) {
|
||||
return fract(sin(seed++ + s)*43758.5453123);
|
||||
}
|
||||
|
||||
vec3 randomHemisphere(vec3 dir)
|
||||
{
|
||||
vec3 uu = normalize(cross(dir, vec3(0.0,1.0,1.0)));
|
||||
vec3 vv = cross(uu, dir);
|
||||
|
||||
vec2 rv2 = vec2(random(1), random(2));
|
||||
|
||||
float ra = sqrt(rv2.y);
|
||||
float rx = ra*cos(6.2831*rv2.x);
|
||||
float ry = ra*sin(6.2831*rv2.x);
|
||||
float rz = sqrt(1.0-rv2.y);
|
||||
vec3 rr = vec3(rx*uu + ry*vv + rz*dir );
|
||||
|
||||
return normalize(rr);
|
||||
}
|
||||
|
||||
vec3 solve()
|
||||
{
|
||||
// Calculate ray direction
|
||||
vec3 view_dir = (_ProjMatrixInv * vec4(_InUV, 0, 1)).xyz;
|
||||
vec3 rayDir = normalize(_ViewMatrix * vec4(view_dir,0)).xyz;
|
||||
Ray primaryRay = Ray(_CamPos / SCALE, rayDir);
|
||||
|
||||
// Raycast
|
||||
HitResult primary = castNodes(primaryRay, 100);
|
||||
if(primary.data > 0)
|
||||
{
|
||||
vec3 color = applyLighting(primary.pos, primaryRay.dir, primary.normal, primary.data);
|
||||
vec3 hitPos = primary.pos-primary.normal*EPSILON;
|
||||
|
||||
// Shadow ray
|
||||
Ray shadowRay = Ray(hitPos, _SunDir);
|
||||
HitResult shadow = castNodes(shadowRay, 50);
|
||||
if(shadow.data > 0) color *= 0.1;
|
||||
|
||||
// Secondary ray
|
||||
// Ray secondRay = Ray(hitPos, randomHemisphere(primary.normal));
|
||||
// HitResult second = castNodes(secondRay, 25);
|
||||
// if(second.data > 0) color += getAlbedo(second.data) * 0.8;
|
||||
|
||||
return color;
|
||||
}
|
||||
|
||||
float up = clamp(dot(primaryRay.dir, vec3(0, 1, 0)) + 0.1, 0, 1);
|
||||
return vec3(0.176, 0.592, 0.901) * up;
|
||||
}
|
||||
|
||||
void main()
|
||||
{
|
||||
seed = 420 * _InUV.x + 1337 * _InUV.y + _Time * 1234;
|
||||
_OutColor = vec4(solve(), 1);
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
|
||||
/*
|
||||
* origin: Point hit on the node
|
||||
* start: Camera pos
|
||||
* dir: Camera view direction (ray direction)
|
||||
* incAxis: Last axis that was used to increment position
|
||||
* addr: Number given by node, brick offset in brick array
|
||||
*/
|
||||
HitResult castBricks(vec3 origin, vec3 start, vec3 dir, vec3 incAxis, uint addr)
|
||||
{
|
||||
vec3 o = origin;
|
||||
|
||||
// Change scale
|
||||
origin = start - origin;
|
||||
origin += dir*0.00001;
|
||||
origin *= BLOCK_SIZE;
|
||||
|
||||
// Same as in casting nodes
|
||||
vec3 pos = floor(origin);
|
||||
vec3 rayInv = 1.0/dir;
|
||||
vec3 raySign = sign(dir);
|
||||
vec3 dist = (pos-origin+0.5 + raySign*0.5) * rayInv;
|
||||
|
||||
// Calculate offset
|
||||
uint y = (addr-1) % BLOCK_TEX_SIZE * BLOCK_SIZE;
|
||||
uint z = (addr-1) / BLOCK_TEX_SIZE * BLOCK_SIZE;
|
||||
ivec3 offset = ivec3(0, y, z);
|
||||
|
||||
for(int i=0;i<110;i++)
|
||||
{
|
||||
// Get brick
|
||||
uint brick = texelFetch(_BricksTexture, offset+ivec3(pos), 0).r;
|
||||
if(brick != 0)
|
||||
{
|
||||
// Hit point
|
||||
vec3 mini = (pos-origin+0.5 - raySign*0.5) * rayInv;
|
||||
float len = max(mini.x, max(mini.y, mini.z));
|
||||
vec3 hitPoint = (origin + dir * len) / BLOCK_SIZE + o;
|
||||
|
||||
// Normal vector (negate previous increment axis and mult by sign)
|
||||
vec3 normal = -incAxis * raySign;
|
||||
return HitResult(brick, hitPoint, normal);
|
||||
}
|
||||
|
||||
// Get new closest axis to increment
|
||||
incAxis = step(dist.xyz, dist.yzx) * step(dist.xyz, dist.zxy);
|
||||
dist += incAxis * raySign * rayInv;
|
||||
pos += incAxis * raySign;
|
||||
|
||||
// Check for bounds
|
||||
if(pos.x < 0 || pos.y < 0 || pos.z < 0) { break; }
|
||||
if(pos.x >= BLOCK_SIZE || pos.y >= BLOCK_SIZE || pos.z >= BLOCK_SIZE) { break; }
|
||||
}
|
||||
|
||||
return HitResult(0, vec3(0,0,0), vec3(0,0,0));
|
||||
}
|
||||
|
||||
/*
|
||||
* origin: Camera position
|
||||
* dir: Ray coming from camera position going through currently drawn pixel
|
||||
*/
|
||||
HitResult castNodes(Ray ray, uint maxSteps)
|
||||
{
|
||||
// Round input pos to nearest voxel
|
||||
vec3 pos = floor(ray.origin);
|
||||
// Inverse ray direction
|
||||
vec3 rayInv = 1.0/ray.dir;
|
||||
// Sign of the ray direction, to know where to increment pos
|
||||
vec3 raySign = sign(ray.dir);
|
||||
// Distance to next voxel in grid
|
||||
vec3 dist = (pos-ray.origin+0.5 + raySign*0.5) * rayInv;
|
||||
|
||||
// Closest axis to increment in grid will be stored here (x=1 or y=1 or z=1)
|
||||
vec3 incAxis = vec3(0,0,0);
|
||||
|
||||
// Iterate
|
||||
for(int i=0;i<maxSteps;i++)
|
||||
{
|
||||
// Get node
|
||||
uint node = texelFetch(_NodesTexture, ivec3(pos), 0).r;
|
||||
if(node != 0)
|
||||
{
|
||||
// Hit point
|
||||
vec3 mini = (pos-ray.origin+0.5 - raySign*0.5) * rayInv;
|
||||
float len = max(0.0, max(mini.x, max(mini.y, mini.z)));
|
||||
vec3 hitPoint = ray.origin + ray.dir * len;
|
||||
|
||||
// Cast brick
|
||||
HitResult result = castBricks(pos, hitPoint, ray.dir, incAxis, node);
|
||||
if(result.data > 0) return result;
|
||||
}
|
||||
|
||||
// Get new closest axis to increment
|
||||
incAxis = step(dist.xyz, dist.yzx) * step(dist.xyz, dist.zxy);
|
||||
dist += incAxis * raySign * rayInv;
|
||||
pos += incAxis * raySign;
|
||||
|
||||
// Outside bounds
|
||||
if(pos.x < 0 || pos.y < 0 || pos.z < 0) { break; }
|
||||
if(pos.x >= BLOCK_TEX_SIZE || pos.y > BLOCK_TEX_SIZE || pos.z >= NODE_TEX_SIZE) { break; }
|
||||
}
|
||||
|
||||
// Not found
|
||||
return HitResult(0, vec3(0,0,0), vec3(0,0,0));
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Returns material albedo for given voxel
|
||||
*/
|
||||
vec3 getAlbedo(uint data) { return _Materials[data-1].albedo.rgb; }
|
||||
float getSpecular(uint data) { return _Materials[data-1].specular; }
|
||||
|
||||
/*
|
||||
point: Hit point
|
||||
view: View vector (camera ray)
|
||||
normal: Normal vector
|
||||
*/
|
||||
vec3 applyLighting(vec3 hitPoint, vec3 view, vec3 normal, uint data)
|
||||
{
|
||||
// Lighting
|
||||
vec3 ambientColor = vec3(0.9, 0.9, 1.0);
|
||||
vec3 ambient = ambientColor * 0.05;
|
||||
vec3 sky = ambientColor * 0.1 * max(normal.y, 0);
|
||||
|
||||
vec3 sunColor = vec3(1.0, 1.0, 0.9);
|
||||
vec3 diffuse = sunColor * max(1.0-dot(normal, _SunDir), 0.0);
|
||||
vec3 specular = sunColor * getSpecular(data) * pow(max(dot(view, reflect(_SunDir, normal)), 0.0), 32);
|
||||
|
||||
// Combine colors
|
||||
return (ambient + sky + diffuse + specular) * getAlbedo(data);
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
struct Ray {
|
||||
vec3 origin;
|
||||
vec3 dir;
|
||||
};
|
||||
|
||||
struct HitResult {
|
||||
uint data; // Voxel data
|
||||
vec3 pos; // Position in world
|
||||
vec3 normal; // Normal vector
|
||||
};
|
||||
Reference in New Issue
Block a user