mirror of https://github.com/axmolengine/axmol.git
365 lines
8.6 KiB
C++
365 lines
8.6 KiB
C++
#include "ShaderGeneratorCommon.h"
|
|
#include <iostream>
|
|
#include <sstream>
|
|
|
|
namespace Effekseer
|
|
{
|
|
namespace Shader
|
|
{
|
|
|
|
namespace
|
|
{
|
|
const char* material_lineargamma_functions = R"(
|
|
|
|
#define FLT_EPSILON 1.192092896e-07
|
|
|
|
float3 PositivePow(float3 base, float3 power)
|
|
{
|
|
return pow(max(abs(base), float3(FLT_EPSILON, FLT_EPSILON, FLT_EPSILON)), power);
|
|
}
|
|
|
|
// based on http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html
|
|
half3 SRGBToLinear(half3 c)
|
|
{
|
|
return min(c, c * (c * (c * 0.305306011 + 0.682171111) + 0.012522878));
|
|
}
|
|
|
|
half4 SRGBToLinear(half4 c)
|
|
{
|
|
return half4(SRGBToLinear(c.rgb), c.a);
|
|
}
|
|
|
|
half3 LinearToSRGB(half3 c)
|
|
{
|
|
return max(1.055 * PositivePow(c, float3(0.416666667,0.416666667,0.416666667)) - 0.055, 0.0);
|
|
}
|
|
|
|
half4 LinearToSRGB(half4 c)
|
|
{
|
|
return half4(LinearToSRGB(c.rgb), c.a);
|
|
}
|
|
|
|
half4 ConvertFromSRGBTexture(half4 c)
|
|
{
|
|
if (predefined_uniform.z == 0.0)
|
|
{
|
|
return c;
|
|
}
|
|
|
|
return LinearToSRGB(c);
|
|
}
|
|
|
|
half4 ConvertToScreen(half4 c)
|
|
{
|
|
if (predefined_uniform.z == 0.0)
|
|
{
|
|
return c;
|
|
}
|
|
|
|
return SRGBToLinear(c);
|
|
}
|
|
|
|
)";
|
|
|
|
}
|
|
|
|
static const char* material_gradient_functions = R"(
|
|
|
|
float LinearStep(float s, float e, float v) {
|
|
return clamp((v - s) / (e - s), 0.0, 1.0);
|
|
}
|
|
|
|
#ifdef EFK__OPENGL2__
|
|
|
|
struct Gradient
|
|
{
|
|
int colorCount;
|
|
int alphaCount;
|
|
int reserved1;
|
|
int reserved2;
|
|
float4 c1;
|
|
float4 c2;
|
|
float4 c3;
|
|
float4 c4;
|
|
float4 c5;
|
|
float4 c6;
|
|
float4 c7;
|
|
float4 c8;
|
|
float2 a1;
|
|
float2 a2;
|
|
float2 a3;
|
|
float2 a4;
|
|
float2 a5;
|
|
float2 a6;
|
|
float2 a7;
|
|
float2 a8;
|
|
};
|
|
|
|
float4 SampleGradient(Gradient gradient, float t) {
|
|
float4 colors[8];
|
|
float2 alphas[8];
|
|
|
|
colors[0] = gradient.c1;
|
|
colors[1] = gradient.c2;
|
|
colors[2] = gradient.c3;
|
|
colors[3] = gradient.c4;
|
|
colors[4] = gradient.c5;
|
|
colors[5] = gradient.c6;
|
|
colors[6] = gradient.c7;
|
|
colors[7] = gradient.c8;
|
|
alphas[0].xy = gradient.a1;
|
|
alphas[1].xy = gradient.a2;
|
|
alphas[2].xy = gradient.a3;
|
|
alphas[3].xy = gradient.a4;
|
|
alphas[4].xy = gradient.a5;
|
|
alphas[5].xy = gradient.a6;
|
|
alphas[6].xy = gradient.a7;
|
|
alphas[7].xy = gradient.a8;
|
|
|
|
float t_clamp = clamp(t, 0.0, 1.0);
|
|
float3 color = colors[0].xyz;
|
|
for(int i = 1; i < 8; i++) {
|
|
float ratio = LinearStep(colors[i-1].w, colors[i].w, t_clamp);
|
|
color = LERP(color, colors[i].xyz, ratio);
|
|
}
|
|
|
|
float alpha = alphas[0].x;
|
|
for(int i = 1; i < 8; i++) {
|
|
float ratio = LinearStep(alphas[i-1].y, alphas[i].y, t_clamp);
|
|
alpha = LERP(alpha, alphas[i].x, ratio);
|
|
}
|
|
return float4(color, alpha);
|
|
}
|
|
|
|
Gradient GradientParameter(float4 param_v, float4 param_c1, float4 param_c2, float4 param_c3, float4 param_c4, float4 param_c5, float4 param_c6, float4 param_c7, float4 param_c8, float4 param_a1, float4 param_a2, float4 param_a3, float4 param_a4)
|
|
{
|
|
Gradient g;
|
|
g.colorCount = int(param_v.x);
|
|
g.alphaCount = int(param_v.y);
|
|
g.reserved1 = int(param_v.z);
|
|
g.reserved2 = int(param_v.w);
|
|
|
|
g.c1 = param_c1;
|
|
g.c2 = param_c2;
|
|
g.c3 = param_c3;
|
|
g.c4 = param_c4;
|
|
g.c5 = param_c5;
|
|
g.c6 = param_c6;
|
|
g.c7 = param_c7;
|
|
g.c8 = param_c8;
|
|
|
|
g.a1 = param_a1.xy;
|
|
g.a2 = param_a1.zw;
|
|
g.a3 = param_a2.xy;
|
|
g.a4 = param_a2.zw;
|
|
g.a5 = param_a3.xy;
|
|
g.a6 = param_a3.zw;
|
|
g.a7 = param_a4.xy;
|
|
g.a8 = param_a4.zw;
|
|
|
|
return g;
|
|
}
|
|
|
|
#else
|
|
|
|
struct Gradient
|
|
{
|
|
int colorCount;
|
|
int alphaCount;
|
|
int reserved1;
|
|
int reserved2;
|
|
float4 colors[8];
|
|
float2 alphas[8];
|
|
};
|
|
|
|
float4 SampleGradient(Gradient gradient, float t) {
|
|
float t_clamp = clamp(t, 0.0, 1.0);
|
|
float3 color = gradient.colors[0].xyz;
|
|
for(int i = 1; i < 8; i++) {
|
|
float ratio = LinearStep(gradient.colors[i-1].w, gradient.colors[i].w, t_clamp);
|
|
color = LERP(color, gradient.colors[i].xyz, ratio);
|
|
}
|
|
|
|
float alpha = gradient.alphas[0].x;
|
|
for(int i = 1; i < 8; i++) {
|
|
float ratio = LinearStep(gradient.alphas[i-1].y, gradient.alphas[i].y, t_clamp);
|
|
alpha = LERP(alpha, gradient.alphas[i].x, ratio);
|
|
}
|
|
return float4(color, alpha);
|
|
}
|
|
|
|
Gradient GradientParameter(float4 param_v, float4 param_c1, float4 param_c2, float4 param_c3, float4 param_c4, float4 param_c5, float4 param_c6, float4 param_c7, float4 param_c8, float4 param_a1, float4 param_a2, float4 param_a3, float4 param_a4)
|
|
{
|
|
Gradient g;
|
|
g.colorCount = int(param_v.x);
|
|
g.alphaCount = int(param_v.y);
|
|
g.reserved1 = int(param_v.z);
|
|
g.reserved2 = int(param_v.w);
|
|
g.colors[0] = param_c1;
|
|
g.colors[1] = param_c2;
|
|
g.colors[2] = param_c3;
|
|
g.colors[3] = param_c4;
|
|
g.colors[4] = param_c5;
|
|
g.colors[5] = param_c6;
|
|
g.colors[6] = param_c7;
|
|
g.colors[7] = param_c8;
|
|
g.alphas[0].xy = param_a1.xy;
|
|
g.alphas[1].xy = param_a1.zw;
|
|
g.alphas[2].xy = param_a2.xy;
|
|
g.alphas[3].xy = param_a2.zw;
|
|
g.alphas[4].xy = param_a3.xy;
|
|
g.alphas[5].xy = param_a3.zw;
|
|
g.alphas[6].xy = param_a4.xy;
|
|
g.alphas[7].xy = param_a4.zw;
|
|
return g;
|
|
}
|
|
|
|
#endif
|
|
|
|
)";
|
|
|
|
static const char* material_noise_functions = R"(
|
|
|
|
float Rand2(float2 n) {
|
|
return FRAC(sin(dot(n, float2(12.9898, 78.233))) * 43758.5453123);
|
|
}
|
|
|
|
float SimpleNoise_Block(float2 uv) {
|
|
int2 uvi = int2(floor(uv));
|
|
float2 uvf = FRAC(uv);
|
|
uvf = uvf * uvf * (3.0 - 2.0 * uvf);
|
|
float x0 = LERP(Rand2(float2(uvi + int2(0, 0))), Rand2(float2(uvi + int2(1, 0))), uvf.x);
|
|
float x1 = LERP(Rand2(float2(uvi + int2(0, 1))), Rand2(float2(uvi + int2(1, 1))), uvf.x);
|
|
return LERP(x0, x1, uvf.y);
|
|
}
|
|
|
|
float SimpleNoise(float2 uv, float scale) {
|
|
const int loop = 3;
|
|
float ret = 0.0;
|
|
for(int i = 0; i < loop; i++) {
|
|
float duration = pow(2.0, float(i));
|
|
float intensity = pow(0.5, float(loop-i));
|
|
ret += SimpleNoise_Block(uv * scale / duration) * intensity;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
)";
|
|
|
|
std::string GetFixedGradient(const char* name, const Gradient& gradient)
|
|
{
|
|
std::stringstream ss;
|
|
|
|
ss << "Gradient " << name << "() {" << std::endl;
|
|
ss << "Gradient g;" << std::endl;
|
|
ss << "g.colorCount = " << gradient.ColorCount << ";" << std::endl;
|
|
ss << "g.alphaCount = " << gradient.AlphaCount << ";" << std::endl;
|
|
ss << "g.reserved1 = 0;" << std::endl;
|
|
ss << "g.reserved2 = 0;" << std::endl;
|
|
|
|
const auto getColorKey = [](const Effekseer::Gradient& gradient, size_t index)
|
|
{
|
|
if (gradient.ColorCount == 0)
|
|
{
|
|
Effekseer::Gradient::ColorKey key;
|
|
key.Color = {1.0f, 1.0f, 1.0f};
|
|
key.Intensity = 1.0f;
|
|
key.Position = 0.0;
|
|
return key;
|
|
}
|
|
else
|
|
{
|
|
if (gradient.ColorCount <= index)
|
|
{
|
|
auto key = gradient.Colors[gradient.ColorCount - 1];
|
|
key.Position += index;
|
|
return key;
|
|
}
|
|
|
|
return gradient.Colors[index];
|
|
}
|
|
};
|
|
|
|
const auto getAlphaKey = [](const Effekseer::Gradient& gradient, size_t index)
|
|
{
|
|
if (gradient.AlphaCount == 0)
|
|
{
|
|
Effekseer::Gradient::AlphaKey key;
|
|
key.Alpha = 1.0f;
|
|
key.Position = 0.0;
|
|
return key;
|
|
}
|
|
else
|
|
{
|
|
if (gradient.AlphaCount <= index)
|
|
{
|
|
auto key = gradient.Alphas[gradient.AlphaCount - 1];
|
|
key.Position += index;
|
|
return key;
|
|
}
|
|
|
|
return gradient.Alphas[index];
|
|
}
|
|
};
|
|
|
|
ss << "#ifdef EFK__OPENGL2__" << std::endl;
|
|
|
|
for (int32_t i = 0; i < gradient.Colors.size(); i++)
|
|
{
|
|
const auto key = getColorKey(gradient, i);
|
|
ss << "g.c" << i + 1 << ".x = " << std::to_string(key.Color[0] * key.Intensity) << ";" << std::endl;
|
|
ss << "g.c" << i + 1 << ".y = " << std::to_string(key.Color[1] * key.Intensity) << ";" << std::endl;
|
|
ss << "g.c" << i + 1 << ".z = " << std::to_string(key.Color[2] * key.Intensity) << ";" << std::endl;
|
|
ss << "g.c" << i + 1 << ".w = " << std::to_string(key.Position) << ";" << std::endl;
|
|
}
|
|
|
|
for (int32_t i = 0; i < gradient.Alphas.size(); i++)
|
|
{
|
|
const auto key = getAlphaKey(gradient, i);
|
|
ss << "g.a" << i + 1 << ".x = " << std::to_string(key.Alpha) << ";" << std::endl;
|
|
ss << "g.a" << i + 1 << ".y = " << std::to_string(key.Position) << ";" << std::endl;
|
|
}
|
|
|
|
ss << "#else" << std::endl;
|
|
|
|
for (int32_t i = 0; i < gradient.Colors.size(); i++)
|
|
{
|
|
const auto key = getColorKey(gradient, i);
|
|
ss << "g.colors[" << i << "].x = " << std::to_string(key.Color[0] * key.Intensity) << ";" << std::endl;
|
|
ss << "g.colors[" << i << "].y = " << std::to_string(key.Color[1] * key.Intensity) << ";" << std::endl;
|
|
ss << "g.colors[" << i << "].z = " << std::to_string(key.Color[2] * key.Intensity) << ";" << std::endl;
|
|
ss << "g.colors[" << i << "].w = " << std::to_string(key.Position) << ";" << std::endl;
|
|
}
|
|
|
|
for (int32_t i = 0; i < gradient.Alphas.size(); i++)
|
|
{
|
|
const auto key = getAlphaKey(gradient, i);
|
|
ss << "g.alphas[" << i << "].x = " << std::to_string(key.Alpha) << ";" << std::endl;
|
|
ss << "g.alphas[" << i << "].y = " << std::to_string(key.Position) << ";" << std::endl;
|
|
}
|
|
|
|
ss << "#endif" << std::endl;
|
|
|
|
ss << "return g; }" << std::endl;
|
|
|
|
return ss.str();
|
|
}
|
|
|
|
const char* GetGradientFunctions()
|
|
{
|
|
return material_gradient_functions;
|
|
}
|
|
|
|
const char* GetNoiseFunctions()
|
|
{
|
|
return material_noise_functions;
|
|
}
|
|
|
|
const char* GetLinearGammaFunctions()
|
|
{
|
|
return material_lineargamma_functions;
|
|
}
|
|
|
|
} // namespace Shader
|
|
} // namespace Effekseer
|