diff --git a/data/shaders/particlefire/generate-spirv.bat b/data/shaders/particlefire/generate-spirv.bat new file mode 100644 index 00000000..fe0e23ed --- /dev/null +++ b/data/shaders/particlefire/generate-spirv.bat @@ -0,0 +1,7 @@ +glslangvalidator -V particle.frag -o particle.frag.spv +glslangvalidator -V particle.vert -o particle.vert.spv +glslangvalidator -V normalmap.frag -o normalmap.frag.spv +glslangvalidator -V normalmap.vert -o normalmap.vert.spv + + + diff --git a/data/shaders/particlefire/normalmap.frag b/data/shaders/particlefire/normalmap.frag new file mode 100644 index 00000000..4de48e15 --- /dev/null +++ b/data/shaders/particlefire/normalmap.frag @@ -0,0 +1,44 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (binding = 1) uniform sampler2D sColorMap; +layout (binding = 2) uniform sampler2D sNormalHeightMap; + +#define lightRadius 35.0 + +layout (location = 0) in vec2 inUV; +layout (location = 1) in vec3 inLightVec; +layout (location = 2) in vec3 inLightVecB; +layout (location = 5) in vec3 inLightDir; +layout (location = 6) in vec3 inViewVec; + +layout (location = 0) out vec4 outFragColor; + +void main(void) +{ + vec3 specularColor = vec3(0.5, 0.5, 0.5); + + float invRadius = 1.0/lightRadius; + float ambient = 0.0; + + vec3 rgb, normal; + + rgb = texture(sColorMap, inUV).rgb; + normal = normalize((texture(sNormalHeightMap, inUV).rgb - 0.5) * 2.0); + + float distSqr = dot(inLightVecB, inLightVecB); + vec3 lVec = inLightVecB * inversesqrt(distSqr); + + float atten = max(clamp(1.0 - invRadius * sqrt(distSqr), 0.0, 1.0), ambient); + float diffuse = clamp(dot(lVec, normal), 0.0, 1.0); + + vec3 light = normalize(-inLightVec); + vec3 view = normalize(inViewVec); + vec3 reflectDir = reflect(-light, normal); + + float specular = pow(max(dot(view, reflectDir), 0.0), 8.0); + + outFragColor = vec4((rgb * atten + (diffuse * rgb + 0.5 * specular * specularColor.rgb)) * atten, 1.0); +} diff --git a/data/shaders/particlefire/normalmap.frag.spv b/data/shaders/particlefire/normalmap.frag.spv new file mode 100644 index 00000000..75b7f9ae Binary files /dev/null and b/data/shaders/particlefire/normalmap.frag.spv differ diff --git a/data/shaders/particlefire/normalmap.vert b/data/shaders/particlefire/normalmap.vert new file mode 100644 index 00000000..53a5914b --- /dev/null +++ b/data/shaders/particlefire/normalmap.vert @@ -0,0 +1,53 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec3 inPos; +layout (location = 1) in vec2 inUV; +layout (location = 2) in vec3 inNormal; +layout (location = 3) in vec3 inTangent; +layout (location = 4) in vec3 inBiTangent; + +layout (binding = 0) uniform UBO +{ + mat4 projection; + mat4 model; + mat4 normal; + vec4 lightPos; + vec4 cameraPos; +} ubo; + +layout (location = 0) out vec2 outUV; +layout (location = 1) out vec3 outLightVec; +layout (location = 2) out vec3 outLightVecB; +layout (location = 5) out vec3 outLightDir; +layout (location = 6) out vec3 outViewVec; + +void main(void) +{ + vec3 vertexPosition = vec3(ubo.model * vec4(inPos, 1.0)); + outLightDir = normalize(ubo.lightPos.xyz - vertexPosition); + + // Setup (t)angent-(b)inormal-(n)ormal matrix for converting + // object coordinates into tangent space + mat3 tbnMatrix; + tbnMatrix[0] = mat3(ubo.normal) * inTangent; + tbnMatrix[1] = mat3(ubo.normal) * inBiTangent; + tbnMatrix[2] = mat3(ubo.normal) * inNormal; + + outLightVec.xyz = vec3(ubo.lightPos.xyz - vertexPosition.xyz) * tbnMatrix; + + vec3 lightDist = ubo.lightPos.xyz - inPos.xyz; + outLightVecB.x = dot(inTangent.xyz, lightDist); + outLightVecB.y = dot(inBiTangent.xyz, lightDist); + outLightVecB.z = dot(inNormal, lightDist); + + outViewVec.x = dot(inTangent, inPos.xyz); + outViewVec.y = dot(inBiTangent, inPos.xyz); + outViewVec.z = dot(inNormal, inPos.xyz); + + outUV = inUV; + + gl_Position = ubo.projection * ubo.model * vec4(inPos, 1.0); +} diff --git a/data/shaders/particlefire/normalmap.vert.spv b/data/shaders/particlefire/normalmap.vert.spv new file mode 100644 index 00000000..8dce1c09 Binary files /dev/null and b/data/shaders/particlefire/normalmap.vert.spv differ diff --git a/data/shaders/particlefire/particle.frag b/data/shaders/particlefire/particle.frag new file mode 100644 index 00000000..4e7b186d --- /dev/null +++ b/data/shaders/particlefire/particle.frag @@ -0,0 +1,47 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (binding = 1) uniform sampler2D samplerSmoke; +layout (binding = 2) uniform sampler2D samplerFire; + +layout (location = 0) in vec4 inColor; +layout (location = 1) in float inPointSize; +layout (location = 2) in float inAlpha; +layout (location = 3) in flat int inType; +layout (location = 4) in float inRotation; + + +layout (location = 0) out vec4 outFragColor; + +void main () +{ + vec4 color; + float alpha = (inAlpha <= 1.0) ? inAlpha : 2.0 - inAlpha; + + // Rotate texture coordinates + // Rotate UV + float rotCenter = 0.5; + float rotCos = cos(inRotation); + float rotSin = sin(inRotation); + vec2 rotUV = vec2( + rotCos * (gl_PointCoord.x - rotCenter) + rotSin * (gl_PointCoord.y - rotCenter) + rotCenter, + rotCos * (gl_PointCoord.y - rotCenter) - rotSin * (gl_PointCoord.x - rotCenter) + rotCenter); + + + if (inType == 0) + { + // Flame + color = texture(samplerFire, rotUV); + outFragColor.a = 0.0; + } + else + { + // Smoke + color = texture(samplerSmoke, rotUV); + outFragColor.a = color.a * alpha; + } + + outFragColor.rgb = color.rgb * inColor.rgb * alpha; +} diff --git a/data/shaders/particlefire/particle.frag.spv b/data/shaders/particlefire/particle.frag.spv new file mode 100644 index 00000000..499e8ea3 Binary files /dev/null and b/data/shaders/particlefire/particle.frag.spv differ diff --git a/data/shaders/particlefire/particle.vert b/data/shaders/particlefire/particle.vert new file mode 100644 index 00000000..d64c669b --- /dev/null +++ b/data/shaders/particlefire/particle.vert @@ -0,0 +1,50 @@ +#version 450 + +#extension GL_ARB_separate_shader_objects : enable +#extension GL_ARB_shading_language_420pack : enable + +layout (location = 0) in vec4 inPos; +layout (location = 1) in vec4 inColor; +layout (location = 2) in float inAlpha; +layout (location = 3) in float inSize; +layout (location = 4) in float inRotation; +layout (location = 5) in int inType; + +layout (location = 0) out vec4 outColor; +layout (location = 1) out float outPointSize; +layout (location = 2) out float outAlpha; +layout (location = 3) out flat int outType; +layout (location = 4) out float outRotation; + +layout (binding = 0) uniform UBO +{ + mat4 projection; + mat4 modelview; + vec2 viewportDim; + float pointSize; +} ubo; + +void main () +{ + gl_PointSize = ubo.pointSize; + outColor = inColor; + outAlpha = inAlpha; + outType = inType; + outRotation = inRotation; + + vec4 eyePos = ubo.modelview * vec4(inPos.xyz, 1.0); + vec4 projVoxel = ubo.projection * vec4(ubo.pointSize, ubo.pointSize, eyePos.z, eyePos.w); + vec2 projSize = ubo.viewportDim * projVoxel.xy / projVoxel.w; + + outPointSize = inSize * 0.25 * (projSize.x + projSize.y); + + gl_PointSize = outPointSize; + + gl_Position = ubo.projection * ubo.modelview * vec4(inPos.xyz, 1.0); + + float pointDist = (gl_Position.w == 0.0) ? 0.00001 : gl_Position.w; + float viewportAR = ubo.viewportDim.x / ubo.viewportDim.y; + + gl_PointSize = (((inSize * 2048.0 * viewportAR) / pointDist) * viewportAR); + +} \ No newline at end of file diff --git a/data/shaders/particlefire/particle.vert.spv b/data/shaders/particlefire/particle.vert.spv new file mode 100644 index 00000000..d1069977 Binary files /dev/null and b/data/shaders/particlefire/particle.vert.spv differ diff --git a/data/textures/particle_fire.ktx b/data/textures/particle_fire.ktx new file mode 100644 index 00000000..9f486f41 Binary files /dev/null and b/data/textures/particle_fire.ktx differ diff --git a/data/textures/particle_smoke.ktx b/data/textures/particle_smoke.ktx new file mode 100644 index 00000000..9c509e68 Binary files /dev/null and b/data/textures/particle_smoke.ktx differ