Redone 18-ibl example. It's now using textures that are filtered with cmft.

This commit is contained in:
Dario Manesku 2016-02-29 01:15:12 +01:00
parent 7b2752c450
commit a079ee53ef
24 changed files with 674 additions and 286 deletions

View file

@ -1,77 +1,124 @@
$input v_view, v_normal $input v_view, v_normal
/* /*
* Copyright 2014 Dario Manesku. All rights reserved. * Copyright 2014-2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/ */
#include "../common/common.sh" #include "../common/common.sh"
#include "uniforms.sh"
uniform vec4 u_params;
uniform mat4 u_mtx;
uniform vec4 u_flags;
uniform vec4 u_rgbDiff;
uniform vec4 u_rgbSpec;
SAMPLERCUBE(s_texCube, 0); SAMPLERCUBE(s_texCube, 0);
SAMPLERCUBE(s_texCubeIrr, 1); SAMPLERCUBE(s_texCubeIrr, 1);
#define u_glossiness u_params.x vec3 calcFresnel(vec3 _cspec, float _dot)
#define u_exposure u_params.y
#define u_diffspec u_params.z
#define u_doDiffuse u_flags.x
#define u_doSpecular u_flags.y
#define u_doDiffuseIbl u_flags.z
#define u_doSpecularIbl u_flags.w
vec3 fresnel(vec3 _cspec, float _dot)
{ {
return _cspec + (1.0 - _cspec) * pow(1.0 - _dot, 5); return _cspec + (1.0 - _cspec)*pow(1.0 - _dot, 5.0);
}
vec3 calcLambert(vec3 _cdiff, float _ndotl)
{
return _cdiff*_ndotl;
}
vec3 calcBlinn(vec3 _cspec, float _ndoth, float _ndotl, float _specPwr)
{
float norm = (_specPwr+8.0)*0.125;
float brdf = pow(_ndoth, _specPwr)*_ndotl*norm;
return _cspec*brdf;
}
float specPwr(float _gloss)
{
return exp2(10.0*_gloss+2.0);
}
// Ref: http://the-witness.net/news/2012/02/seamless-cube-map-filtering/
vec3 fixCubeLookup(vec3 _v, float _lod, float _topLevelCubeSize)
{
float ax = abs(_v.x);
float ay = abs(_v.y);
float az = abs(_v.z);
float vmax = max(max(ax, ay), az);
float scale = 1.0 - exp2(_lod) / _topLevelCubeSize;
if (ax != vmax) { _v.x *= scale; }
if (ay != vmax) { _v.y *= scale; }
if (az != vmax) { _v.z *= scale; }
return _v;
} }
void main() void main()
{ {
vec3 light = vec3(0.0, 0.0, -1.0); // Light.
vec3 clight = vec3(1.0, 1.0, 1.0); vec3 ld = normalize(u_lightDir);
vec3 clight = u_lightCol;
vec3 v = v_view; // Input.
vec3 n = normalize(v_normal); vec3 nn = normalize(v_normal);
vec3 l = normalize(light); vec3 vv = normalize(v_view);
vec3 h = normalize(v + l); vec3 hh = normalize(vv + ld);
float ndotl = clamp(dot(n, l), 0.0, 1.0); //diff float ndotv = clamp(dot(nn, vv), 0.0, 1.0);
float ndoth = clamp(dot(n, h), 0.0, 1.0); //spec float ndotl = clamp(dot(nn, ld), 0.0, 1.0);
float vdoth = clamp(dot(v, h), 0.0, 1.0); //spec fresnel float ndoth = clamp(dot(nn, hh), 0.0, 1.0);
float ndotv = clamp(dot(n, v), 0.0, 1.0); //env spec fresnel float hdotv = clamp(dot(hh, vv), 0.0, 1.0);
vec3 r = 2.0*ndotv*n - v; // reflect(v, n); // Material params.
vec3 albedo = u_rgbDiff.xyz;
float reflectivity = u_reflectivity;
float gloss = u_glossiness;
vec3 cubeR = normalize(mul(u_mtx, vec4(r, 0.0)).xyz); // Reflection.
vec3 cubeN = normalize(mul(u_mtx, vec4(n, 0.0)).xyz); vec3 refl;
if (0.0 == u_metalOrSpec) // Metalness workflow.
{
refl = mix(vec3_splat(0.04), albedo, reflectivity);
}
else // Specular workflow.
{
refl = u_rgbSpec.xyz * vec3_splat(reflectivity);
}
vec3 dirF0 = calcFresnel(refl, hdotv);
vec3 envF0 = calcFresnel(refl, ndotv);
float mipLevel = min((1.0 - u_glossiness)*11.0 + 1.0, 8.0); // Direct lighting.
vec3 cenv = textureCubeLod(s_texCube, cubeR, mipLevel).xyz; vec3 dirSpec = dirF0;
vec3 dirDiff = albedo * 1.0-dirF0;
vec3 kd = u_rgbDiff.xyz; vec3 lambert = u_doDiffuse * calcLambert(dirDiff, ndotl);
vec3 ks = u_rgbSpec.xyz; vec3 blinn = u_doSpecular * calcBlinn(dirSpec, ndoth, ndotl, specPwr(gloss));
vec3 direct = (lambert + blinn)*clight;
vec3 cs = ks * u_diffspec; // Indirect lighting.
vec3 cd = kd * (1.0 - cs); vec3 envSpec = envF0;
vec3 envDiff = albedo * 1.0-envF0;
vec3 diff = cd; // Note: Environment textures are filtered with cmft: https://github.com/dariomanesku/cmft
float pwr = exp2(u_glossiness * 11.0 + 1.0); // Params used:
vec3 spec = cs * pow(ndoth, pwr) * ( (pwr + 8.0)/8.0) * fresnel(cs, vdoth); // --excludeBase true //!< First level mip is not filtered.
// --mipCount 7 //!< 7 mip levels are used in total, [256x256 .. 4x4]. Lower res mip maps should be avoided.
// --glossScale 10 //!< Spec power scale. See: specPwr().
// --glossBias 2 //!< Spec power bias. See: specPwr().
// --edgeFixup warp //!< This must be used on DirectX9. When fileted with 'warp', fixCubeLookup() should be used.
float mip = 1.0 + 5.0*(1.0 - gloss); // Use mip levels [1..6] for radiance.
vec3 ambspec = fresnel(cs, ndotv) * cenv; mat4 mtx;
vec3 ambdiff = cd * textureCube(s_texCubeIrr, cubeN).xyz; mtx[0] = u_mtx0;
mtx[1] = u_mtx1;
mtx[2] = u_mtx2;
mtx[3] = u_mtx3;
vec3 vr = 2.0*ndotv*nn - vv; // Same as: -reflect(vv, nn);
vec3 cubeR = normalize(instMul(mtx, vec4(vr, 0.0)).xyz);
vec3 cubeN = normalize(instMul(mtx, vec4(nn, 0.0)).xyz);
cubeR = fixCubeLookup(cubeR, mip, 256.0);
vec3 lc = ( diff * u_doDiffuse + spec * u_doSpecular ) * ndotl * clight; vec3 radiance = u_doDiffuseIbl * envSpec * toLinear(textureCubeLod(s_texCube, cubeR, mip).xyz);
vec3 ec = (ambdiff * u_doDiffuseIbl + ambspec * u_doSpecularIbl); vec3 irradiance = u_doSpecularIbl * envDiff * toLinear(textureCube(s_texCubeIrr, cubeN).xyz);
vec3 indirect = radiance + irradiance;
vec3 color = lc + ec; // Color.
vec3 color = direct + indirect;
color = color * exp2(u_exposure); color = color * exp2(u_exposure);
gl_FragColor.xyz = toFilmic(color); gl_FragColor.xyz = toFilmic(color);
gl_FragColor.w = 1.0; gl_FragColor.w = 1.0;
} }

View file

@ -1,22 +1,45 @@
$input v_dir $input v_dir
/* /*
* Copyright 2014 Dario Manesku. All rights reserved. * Copyright 2014-2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/ */
#include "../common/common.sh" #include "../common/common.sh"
#include "uniforms.sh"
SAMPLERCUBE(s_texCube, 0); SAMPLERCUBE(s_texCube, 0);
SAMPLERCUBE(s_texCubeIrr, 1);
uniform vec4 u_params; // Ref: http://the-witness.net/news/2012/02/seamless-cube-map-filtering/
#define u_exposure u_params.y vec3 fixCubeLookup(vec3 _v, float _lod, float _topLevelCubeSize)
{
float ax = abs(_v.x);
float ay = abs(_v.y);
float az = abs(_v.z);
float vmax = max(max(ax, ay), az);
float scale = 1.0 - exp2(_lod) / _topLevelCubeSize;
if (ax != vmax) { _v.x *= scale; }
if (ay != vmax) { _v.y *= scale; }
if (az != vmax) { _v.z *= scale; }
return _v;
}
void main() void main()
{ {
vec3 dir = normalize(v_dir); vec3 dir = normalize(v_dir);
vec4 color = textureCubeLod(s_texCube, dir, 0.0); vec4 color;
if (u_bgType == 7.0)
{
color = toLinear(textureCube(s_texCubeIrr, dir));
}
else
{
float lod = u_bgType;
dir = fixCubeLookup(dir, lod, 256.0);
color = toLinear(textureCubeLod(s_texCube, dir, lod));
}
color *= exp2(u_exposure); color *= exp2(u_exposure);
gl_FragColor = toFilmic(color); gl_FragColor = toFilmic(color);

View file

@ -1,5 +1,5 @@
/* /*
* Copyright 2014 Dario Manesku. All rights reserved. * Copyright 2014-2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/ */
@ -18,86 +18,51 @@ static float s_texelHalf = 0.0f;
struct Uniforms struct Uniforms
{ {
enum { NumVec4 = 12 };
void init() void init()
{ {
m_time = 0.0f; u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, NumVec4);
bx::mtxIdentity(m_mtx);
u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Mat4);
u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4);
u_flags = bgfx::createUniform("u_flags", bgfx::UniformType::Vec4);
u_camPos = bgfx::createUniform("u_camPos", bgfx::UniformType::Vec4);
u_rgbDiff = bgfx::createUniform("u_rgbDiff", bgfx::UniformType::Vec4);
u_rgbSpec = bgfx::createUniform("u_rgbSpec", bgfx::UniformType::Vec4);
} }
// Call this once per frame. void submit()
void submitPerFrameUniforms()
{ {
bgfx::setUniform(u_mtx, m_mtx); bgfx::setUniform(u_params, m_params, NumVec4);
bgfx::setUniform(u_flags, m_flags);
bgfx::setUniform(u_camPos, m_camPosTime);
bgfx::setUniform(u_rgbDiff, m_rgbDiff);
bgfx::setUniform(u_rgbSpec, m_rgbSpec);
}
// Call this before each draw call.
void submitPerDrawUniforms()
{
bgfx::setUniform(u_params, m_params);
} }
void destroy() void destroy()
{ {
bgfx::destroyUniform(u_rgbSpec);
bgfx::destroyUniform(u_rgbDiff);
bgfx::destroyUniform(u_camPos);
bgfx::destroyUniform(u_flags);
bgfx::destroyUniform(u_params); bgfx::destroyUniform(u_params);
bgfx::destroyUniform(u_mtx);
} }
union union
{ {
struct struct
{ {
float m_glossiness; union
float m_exposure; {
float m_diffspec; float m_mtx[16];
float m_time; /* 0*/ struct { float m_mtx0[4]; };
/* 1*/ struct { float m_mtx1[4]; };
/* 2*/ struct { float m_mtx2[4]; };
/* 3*/ struct { float m_mtx3[4]; };
};
/* 4*/ struct { float m_glossiness, m_reflectivity, m_exposure, m_bgType; };
/* 5*/ struct { float m_metalOrSpec, m_unused5[3]; };
/* 6*/ struct { float m_doDiffuse, m_doSpecular, m_doDiffuseIbl, m_doSpecularIbl; };
/* 7*/ struct { float m_cameraPos[3], m_unused7[1]; };
/* 8*/ struct { float m_rgbDiff[4]; };
/* 9*/ struct { float m_rgbSpec[4]; };
/*10*/ struct { float m_lightDir[3], m_unused10[1]; };
/*11*/ struct { float m_lightCol[3], m_unused11[1]; };
}; };
float m_params[4]; float m_params[NumVec4*4];
}; };
union
{
struct
{
float m_diffuse;
float m_specular;
float m_diffuseIbl;
float m_specularIbl;
};
float m_flags[4];
};
float m_mtx[16];
float m_camPosTime[4];
float m_rgbDiff[4];
float m_rgbSpec[4];
bgfx::UniformHandle u_mtx;
bgfx::UniformHandle u_params; bgfx::UniformHandle u_params;
bgfx::UniformHandle u_flags;
bgfx::UniformHandle u_camPos;
bgfx::UniformHandle u_rgbDiff;
bgfx::UniformHandle u_rgbSpec;
}; };
static Uniforms s_uniforms;
struct PosColorTexCoord0Vertex struct PosColorTexCoord0Vertex
{ {
float m_x; float m_x;
@ -181,11 +146,8 @@ struct LightProbe
{ {
enum Enum enum Enum
{ {
Wells, Bolonga,
Uffizi, Kyoto,
Pisa,
Ennis,
Grace,
Count Count
}; };
@ -213,6 +175,253 @@ struct LightProbe
bgfx::TextureHandle m_texIrr; bgfx::TextureHandle m_texIrr;
}; };
struct Camera
{
Camera()
{
reset();
}
void reset()
{
m_target.curr[0] = 0.0f;
m_target.curr[1] = 0.0f;
m_target.curr[2] = 0.0f;
m_target.dest[0] = 0.0f;
m_target.dest[1] = 0.0f;
m_target.dest[2] = 0.0f;
m_pos.curr[0] = 0.0f;
m_pos.curr[1] = 0.0f;
m_pos.curr[2] = -3.0f;
m_pos.dest[0] = 0.0f;
m_pos.dest[1] = 0.0f;
m_pos.dest[2] = -3.0f;
m_orbit[0] = 0.0f;
m_orbit[1] = 0.0f;
}
void mtxLookAt(float* _outViewMtx)
{
bx::mtxLookAt(_outViewMtx, m_pos.curr, m_target.curr);
}
void orbit(float _dx, float _dy)
{
m_orbit[0] += _dx;
m_orbit[1] += _dy;
}
void dolly(float _dz)
{
const float cnear = 1.0f;
const float cfar = 10.0f;
const float toTarget[3] =
{
m_target.dest[0] - m_pos.dest[0],
m_target.dest[1] - m_pos.dest[1],
m_target.dest[2] - m_pos.dest[2],
};
const float toTargetLen = bx::vec3Length(toTarget);
const float invToTargetLen = 1.0f/(toTargetLen+FLT_MIN);
const float toTargetNorm[3] =
{
toTarget[0]*invToTargetLen,
toTarget[1]*invToTargetLen,
toTarget[2]*invToTargetLen,
};
float delta = toTargetLen*_dz;
float newLen = toTargetLen + delta;
if ( (cnear < newLen || _dz < 0.0f)
&& (newLen < cfar || _dz > 0.0f) )
{
m_pos.dest[0] += toTargetNorm[0]*delta;
m_pos.dest[1] += toTargetNorm[1]*delta;
m_pos.dest[2] += toTargetNorm[2]*delta;
}
}
void consumeOrbit(float _amount)
{
float consume[2];
consume[0] = m_orbit[0]*_amount;
consume[1] = m_orbit[1]*_amount;
m_orbit[0] -= consume[0];
m_orbit[1] -= consume[1];
const float toPos[3] =
{
m_pos.curr[0] - m_target.curr[0],
m_pos.curr[1] - m_target.curr[1],
m_pos.curr[2] - m_target.curr[2],
};
const float toPosLen = bx::vec3Length(toPos);
const float invToPosLen = 1.0f/(toPosLen+FLT_MIN);
const float toPosNorm[3] =
{
toPos[0]*invToPosLen,
toPos[1]*invToPosLen,
toPos[2]*invToPosLen,
};
float ll[2];
latLongFromVec(ll[0], ll[1], toPosNorm);
ll[0] += consume[0];
ll[1] -= consume[1];
ll[1] = bx::fclamp(ll[1], 0.02f, 0.98f);
float tmp[3];
vecFromLatLong(tmp, ll[0], ll[1]);
float diff[3];
diff[0] = (tmp[0]-toPosNorm[0])*toPosLen;
diff[1] = (tmp[1]-toPosNorm[1])*toPosLen;
diff[2] = (tmp[2]-toPosNorm[2])*toPosLen;
m_pos.curr[0] += diff[0];
m_pos.curr[1] += diff[1];
m_pos.curr[2] += diff[2];
m_pos.dest[0] += diff[0];
m_pos.dest[1] += diff[1];
m_pos.dest[2] += diff[2];
}
void update(float _dt)
{
const float amount = bx::fmin(_dt/0.12f, 1.0f);
consumeOrbit(amount);
m_target.curr[0] = bx::flerp(m_target.curr[0], m_target.dest[0], amount);
m_target.curr[1] = bx::flerp(m_target.curr[1], m_target.dest[1], amount);
m_target.curr[2] = bx::flerp(m_target.curr[2], m_target.dest[2], amount);
m_pos.curr[0] = bx::flerp(m_pos.curr[0], m_pos.dest[0], amount);
m_pos.curr[1] = bx::flerp(m_pos.curr[1], m_pos.dest[1], amount);
m_pos.curr[2] = bx::flerp(m_pos.curr[2], m_pos.dest[2], amount);
}
void envViewMtx(float* _mtx)
{
const float toTarget[3] =
{
m_target.curr[0] - m_pos.curr[0],
m_target.curr[1] - m_pos.curr[1],
m_target.curr[2] - m_pos.curr[2],
};
const float toTargetLen = bx::vec3Length(toTarget);
const float invToTargetLen = 1.0f/(toTargetLen+FLT_MIN);
const float toTargetNorm[3] =
{
toTarget[0]*invToTargetLen,
toTarget[1]*invToTargetLen,
toTarget[2]*invToTargetLen,
};
float tmp[3];
const float fakeUp[3] = { 0.0f, 1.0f, 0.0f };
float right[3];
bx::vec3Cross(tmp, fakeUp, toTargetNorm);
bx::vec3Norm(right, tmp);
float up[3];
bx::vec3Cross(tmp, toTargetNorm, right);
bx::vec3Norm(up, tmp);
_mtx[ 0] = right[0];
_mtx[ 1] = right[1];
_mtx[ 2] = right[2];
_mtx[ 3] = 0.0f;
_mtx[ 4] = up[0];
_mtx[ 5] = up[1];
_mtx[ 6] = up[2];
_mtx[ 7] = 0.0f;
_mtx[ 8] = toTargetNorm[0];
_mtx[ 9] = toTargetNorm[1];
_mtx[10] = toTargetNorm[2];
_mtx[11] = 0.0f;
_mtx[12] = 0.0f;
_mtx[13] = 0.0f;
_mtx[14] = 0.0f;
_mtx[15] = 1.0f;
}
static inline void vecFromLatLong(float _vec[3], float _u, float _v)
{
const float phi = _u * 2.0f*bx::pi;
const float theta = _v * bx::pi;
const float st = bx::fsin(theta);
const float sp = bx::fsin(phi);
const float ct = bx::fcos(theta);
const float cp = bx::fcos(phi);
_vec[0] = -st*sp;
_vec[1] = ct;
_vec[2] = -st*cp;
}
static inline void latLongFromVec(float& _u, float& _v, const float _vec[3])
{
const float phi = atan2f(_vec[0], _vec[2]);
const float theta = acosf(_vec[1]);
_u = (bx::pi + phi)*bx::invPi*0.5f;
_v = theta*bx::invPi;
}
struct Interp3f
{
float curr[3];
float dest[3];
};
Interp3f m_target;
Interp3f m_pos;
float m_orbit[2];
};
struct Mouse
{
Mouse()
{
m_dx = 0.0f;
m_dy = 0.0f;
m_prevMx = 0.0f;
m_prevMx = 0.0f;
m_scroll = 0;
m_scrollPrev = 0;
}
void update(float _mx, float _my, int32_t _mz, uint32_t _width, uint32_t _height)
{
const float widthf = float(int32_t(_width));
const float heightf = float(int32_t(_height));
// Delta movement.
m_dx = float(_mx - m_prevMx)/widthf;
m_dy = float(_my - m_prevMy)/heightf;
m_prevMx = _mx;
m_prevMy = _my;
// Scroll.
m_scroll = _mz - m_scrollPrev;
m_scrollPrev = _mz;
}
float m_dx; // Screen space.
float m_dy;
float m_prevMx;
float m_prevMy;
int32_t m_scroll;
int32_t m_scrollPrev;
};
int _main_(int _argc, char** _argv) int _main_(int _argc, char** _argv)
{ {
Args args(_argc, _argv); Args args(_argc, _argv);
@ -240,18 +449,16 @@ int _main_(int _argc, char** _argv)
imguiCreate(); imguiCreate();
// Uniforms. // Uniforms.
s_uniforms.init(); Uniforms uniforms;
uniforms.init();
// Vertex declarations. // Vertex declarations.
PosColorTexCoord0Vertex::init(); PosColorTexCoord0Vertex::init();
LightProbe lightProbes[LightProbe::Count]; LightProbe lightProbes[LightProbe::Count];
lightProbes[LightProbe::Wells ].load("wells"); lightProbes[LightProbe::Bolonga].load("bolonga");
lightProbes[LightProbe::Uffizi].load("uffizi"); lightProbes[LightProbe::Kyoto ].load("kyoto");
lightProbes[LightProbe::Pisa ].load("pisa"); LightProbe::Enum currentLightProbe = LightProbe::Bolonga;
lightProbes[LightProbe::Ennis ].load("ennis");
lightProbes[LightProbe::Grace ].load("grace");
LightProbe::Enum currentLightProbe = LightProbe::Wells;
bgfx::UniformHandle u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Mat4); bgfx::UniformHandle u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Mat4);
bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4); bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4);
@ -266,43 +473,73 @@ int _main_(int _argc, char** _argv)
Mesh* meshBunny; Mesh* meshBunny;
meshBunny = meshLoad("meshes/bunny.bin"); meshBunny = meshLoad("meshes/bunny.bin");
Mesh* meshOrb;
meshOrb = meshLoad("meshes/orb.bin");
Camera camera;
Mouse mouse;
struct Settings struct Settings
{ {
float m_speed; Settings()
{
m_envRotCurr = 0.0f;
m_envRotDest = 0.0f;
m_lightDir[0] = -0.8f;
m_lightDir[1] = 0.2f;
m_lightDir[2] = -0.5f;
m_lightCol[0] = 1.0f;
m_lightCol[1] = 1.0f;
m_lightCol[2] = 1.0f;
m_glossiness = 0.7f;
m_exposure = 0.0f;
m_bgType = 3.0f;
m_radianceSlider = 2.0f;
m_reflectivity = 0.85f;
m_rgbDiff[0] = 1.0f;
m_rgbDiff[1] = 1.0f;
m_rgbDiff[2] = 1.0f;
m_rgbSpec[0] = 1.0f;
m_rgbSpec[1] = 1.0f;
m_rgbSpec[2] = 1.0f;
m_lod = 0.0f;
m_doDiffuse = false;
m_doSpecular = false;
m_doDiffuseIbl = true;
m_doSpecularIbl = true;
m_showLightColorWheel = true;
m_showDiffColorWheel = true;
m_showSpecColorWheel = true;
m_metalOrSpec = 0;
m_meshSelection = 0;
m_crossCubemapPreview = ImguiCubemap::Latlong;
}
float m_envRotCurr;
float m_envRotDest;
float m_lightDir[3];
float m_lightCol[3];
float m_glossiness; float m_glossiness;
float m_exposure; float m_exposure;
float m_diffspec; float m_radianceSlider;
float m_bgType;
float m_reflectivity;
float m_rgbDiff[3]; float m_rgbDiff[3];
float m_rgbSpec[3]; float m_rgbSpec[3];
bool m_diffuse; float m_lod;
bool m_specular; bool m_doDiffuse;
bool m_diffuseIbl; bool m_doSpecular;
bool m_specularIbl; bool m_doDiffuseIbl;
bool m_doSpecularIbl;
bool m_showLightColorWheel;
bool m_showDiffColorWheel; bool m_showDiffColorWheel;
bool m_showSpecColorWheel; bool m_showSpecColorWheel;
uint8_t m_metalOrSpec;
uint8_t m_meshSelection;
ImguiCubemap::Enum m_crossCubemapPreview; ImguiCubemap::Enum m_crossCubemapPreview;
}; };
Settings settings; Settings settings;
settings.m_speed = 0.37f;
settings.m_glossiness = 1.0f;
settings.m_exposure = 0.0f;
settings.m_diffspec = 0.65f;
settings.m_rgbDiff[0] = 0.2f;
settings.m_rgbDiff[1] = 0.2f;
settings.m_rgbDiff[2] = 0.2f;
settings.m_rgbSpec[0] = 1.0f;
settings.m_rgbSpec[1] = 1.0f;
settings.m_rgbSpec[2] = 1.0f;
settings.m_diffuse = true;
settings.m_specular = true;
settings.m_diffuseIbl = true;
settings.m_specularIbl = true;
settings.m_showDiffColorWheel = true;
settings.m_showSpecColorWheel = false;
settings.m_crossCubemapPreview = ImguiCubemap::Cross;
float time = 0.0f;
int32_t leftScrollArea = 0; int32_t leftScrollArea = 0;
@ -320,127 +557,114 @@ int _main_(int _argc, char** _argv)
); );
static int32_t rightScrollArea = 0; static int32_t rightScrollArea = 0;
imguiBeginScrollArea("Settings", width - 256 - 10, 10, 256, 540, &rightScrollArea); imguiBeginScrollArea("", width - 256 - 10, 10, 256, 700, &rightScrollArea);
imguiLabel("Shade:"); imguiLabel("Environment light:");
imguiSeparator(); imguiIndent();
imguiBool("Diffuse", settings.m_diffuse); imguiBool("IBL Diffuse", settings.m_doDiffuseIbl);
imguiBool("Specular", settings.m_specular); imguiBool("IBL Specular", settings.m_doSpecularIbl);
imguiBool("IBL Diffuse", settings.m_diffuseIbl); currentLightProbe = LightProbe::Enum(imguiTabs(currentLightProbe, true, ImguiAlign::LeftIndented, 16, 2, 2
imguiBool("IBL Specular", settings.m_specularIbl); , "Bolonga"
, "Kyoto"
imguiSeparatorLine();
imguiSlider("Speed", settings.m_speed, 0.0f, 1.0f, 0.01f);
imguiSeparatorLine();
imguiSeparator();
imguiSlider("Exposure", settings.m_exposure, -8.0f, 8.0f, 0.01f);
imguiSeparator();
imguiLabel("Environment:");
currentLightProbe = LightProbe::Enum(imguiChoose(currentLightProbe
, "Wells"
, "Uffizi"
, "Pisa"
, "Ennis"
, "Grace"
) ); ) );
static float lod = 0.0f; if (imguiCube(lightProbes[currentLightProbe].m_tex, settings.m_lod, settings.m_crossCubemapPreview, true) )
if (imguiCube(lightProbes[currentLightProbe].m_tex, lod, settings.m_crossCubemapPreview, true) )
{ {
settings.m_crossCubemapPreview = ImguiCubemap::Enum( (settings.m_crossCubemapPreview+1) % ImguiCubemap::Count); settings.m_crossCubemapPreview = ImguiCubemap::Enum( (settings.m_crossCubemapPreview+1) % ImguiCubemap::Count);
} }
imguiSlider("Texture LOD", lod, 0.0f, 10.1f, 0.1f); imguiSlider("Texture LOD", settings.m_lod, 0.0f, 10.1f, 0.1f);
imguiUnindent();
imguiSeparator(8);
imguiLabel("Directional light:");
imguiIndent();
imguiBool("Diffuse", settings.m_doDiffuse);
imguiBool("Specular", settings.m_doSpecular);
const bool doDirectLighting = settings.m_doDiffuse || settings.m_doSpecular;
imguiSlider("Light direction X", settings.m_lightDir[0], -1.0f, 1.0f, 0.1f, doDirectLighting);
imguiSlider("Light direction Y", settings.m_lightDir[1], -1.0f, 1.0f, 0.1f, doDirectLighting);
imguiSlider("Light direction Z", settings.m_lightDir[2], -1.0f, 1.0f, 0.1f, doDirectLighting);
imguiColorWheel("Color:", settings.m_lightCol, settings.m_showLightColorWheel, 0.6f, doDirectLighting);
imguiUnindent();
imguiSeparator(8);
imguiLabel("Background:");
imguiIndent();
{
int32_t selection;
if (0.0f == settings.m_bgType) { selection = 0; }
else if (7.0f == settings.m_bgType) { selection = 2; }
else { selection = 1; }
selection = imguiTabs(selection, true, ImguiAlign::LeftIndented, 16, 2, 3
, "Skybox"
, "Radiance"
, "Irradiance"
);
if (0 == selection) { settings.m_bgType = 0.0f; }
else if (2 == selection) { settings.m_bgType = 7.0f; }
else { settings.m_bgType = settings.m_radianceSlider; }
const bool isRadiance = (selection == 1);
imguiSlider("Mip level", settings.m_radianceSlider, 1.0f, 6.0f, 0.1f, isRadiance);
}
imguiUnindent();
imguiSeparator(8);
imguiLabel("Post processing:");
imguiIndent();
imguiSlider("Exposure", settings.m_exposure, -4.0f, 4.0f, 0.1f);
imguiUnindent();
imguiSeparator();
imguiEndScrollArea(); imguiEndScrollArea();
imguiBeginScrollArea("Settings", 10, 70, 256, 576, &leftScrollArea); imguiBeginScrollArea("", 10, 70, 256, 636, &leftScrollArea);
imguiLabel("Material properties:"); imguiLabel("Mesh:");
imguiSeparator(); imguiIndent();
imguiSlider("Diffuse - Specular", settings.m_diffspec, 0.0f, 1.0f, 0.01f); settings.m_meshSelection = imguiChoose(settings.m_meshSelection, "Bunny", "Orbs");
imguiSlider("Glossiness" , settings.m_glossiness, 0.0f, 1.0f, 0.01f); imguiUnindent();
imguiSeparator();
imguiColorWheel("Diffuse color:", &settings.m_rgbDiff[0], settings.m_showDiffColorWheel); const bool isBunny = (0 == settings.m_meshSelection);
imguiSeparator(); if (!isBunny)
imguiColorWheel("Specular color:", &settings.m_rgbSpec[0], settings.m_showSpecColorWheel);
imguiSeparator();
imguiLabel("Predefined materials:");
imguiSeparator();
if (imguiButton("Gold") )
{ {
settings.m_glossiness = 0.8f; settings.m_metalOrSpec = 0.0f;
settings.m_diffspec = 1.0f;
settings.m_rgbDiff[0] = 0.0f;
settings.m_rgbDiff[1] = 0.0f;
settings.m_rgbDiff[2] = 0.0f;
settings.m_rgbSpec[0] = 1.0f;
settings.m_rgbSpec[1] = 0.86f;
settings.m_rgbSpec[2] = 0.58f;
} }
if (imguiButton("Copper") ) imguiSeparator(4);
{ imguiLabel("Workflow:");
settings.m_glossiness = 0.67f; imguiIndent();
settings.m_diffspec = 1.0f; if (imguiCheck("Metalness", 0 == settings.m_metalOrSpec, isBunny) ) { settings.m_metalOrSpec = 0; }
if (imguiCheck("Specular", 1 == settings.m_metalOrSpec, isBunny) ) { settings.m_metalOrSpec = 1; }
imguiUnindent();
settings.m_rgbDiff[0] = 0.0f; imguiSeparator(4);
settings.m_rgbDiff[1] = 0.0f; imguiLabel("Material:");
settings.m_rgbDiff[2] = 0.0f; imguiIndent();
imguiSlider("Glossiness", settings.m_glossiness, 0.0f, 1.0f, 0.01f, isBunny);
imguiSlider(0 == settings.m_metalOrSpec ? "Metalness" : "Diffuse - Specular", settings.m_reflectivity, 0.0f, 1.0f, 0.01f, isBunny);
imguiUnindent();
settings.m_rgbSpec[0] = 0.98f; imguiColorWheel("Diffuse:", &settings.m_rgbDiff[0], settings.m_showDiffColorWheel, 0.7f);
settings.m_rgbSpec[1] = 0.82f; imguiSeparator();
settings.m_rgbSpec[2] = 0.76f; imguiColorWheel("Specular:", &settings.m_rgbSpec[0], settings.m_showSpecColorWheel, 0.7f, (1 == settings.m_metalOrSpec) && isBunny);
}
if (imguiButton("Titanium") )
{
settings.m_glossiness = 0.57f;
settings.m_diffspec = 1.0f;
settings.m_rgbDiff[0] = 0.0f;
settings.m_rgbDiff[1] = 0.0f;
settings.m_rgbDiff[2] = 0.0f;
settings.m_rgbSpec[0] = 0.76f;
settings.m_rgbSpec[1] = 0.73f;
settings.m_rgbSpec[2] = 0.71f;
}
if (imguiButton("Steel") )
{
settings.m_glossiness = 0.82f;
settings.m_diffspec = 1.0f;
settings.m_rgbDiff[0] = 0.0f;
settings.m_rgbDiff[1] = 0.0f;
settings.m_rgbDiff[2] = 0.0f;
settings.m_rgbSpec[0] = 0.77f;
settings.m_rgbSpec[1] = 0.78f;
settings.m_rgbSpec[2] = 0.77f;
}
imguiEndScrollArea(); imguiEndScrollArea();
imguiEndFrame(); imguiEndFrame();
s_uniforms.m_glossiness = settings.m_glossiness; uniforms.m_glossiness = settings.m_glossiness;
s_uniforms.m_exposure = settings.m_exposure; uniforms.m_reflectivity = settings.m_reflectivity;
s_uniforms.m_diffspec = settings.m_diffspec; uniforms.m_exposure = settings.m_exposure;
s_uniforms.m_flags[0] = float(settings.m_diffuse); uniforms.m_bgType = settings.m_bgType;
s_uniforms.m_flags[1] = float(settings.m_specular); uniforms.m_metalOrSpec = float(settings.m_metalOrSpec);
s_uniforms.m_flags[2] = float(settings.m_diffuseIbl); uniforms.m_doDiffuse = float(settings.m_doDiffuse);
s_uniforms.m_flags[3] = float(settings.m_specularIbl); uniforms.m_doSpecular = float(settings.m_doSpecular);
memcpy(s_uniforms.m_rgbDiff, settings.m_rgbDiff, 3*sizeof(float) ); uniforms.m_doDiffuseIbl = float(settings.m_doDiffuseIbl);
memcpy(s_uniforms.m_rgbSpec, settings.m_rgbSpec, 3*sizeof(float) ); uniforms.m_doSpecularIbl = float(settings.m_doSpecularIbl);
memcpy(uniforms.m_rgbDiff, settings.m_rgbDiff, 3*sizeof(float) );
s_uniforms.submitPerFrameUniforms(); memcpy(uniforms.m_rgbSpec, settings.m_rgbSpec, 3*sizeof(float) );
memcpy(uniforms.m_lightDir, settings.m_lightDir, 3*sizeof(float) );
memcpy(uniforms.m_lightCol, settings.m_lightCol, 3*sizeof(float) );
int64_t now = bx::getHPCounter(); int64_t now = bx::getHPCounter();
static int64_t last = now; static int64_t last = now;
@ -448,9 +672,7 @@ int _main_(int _argc, char** _argv)
last = now; last = now;
const double freq = double(bx::getHPFrequency() ); const double freq = double(bx::getHPFrequency() );
const double toMs = 1000.0/freq; const double toMs = 1000.0/freq;
const double deltaTimeSec = double(frameTime)/freq;
time += (float)(frameTime*settings.m_speed/freq);
s_uniforms.m_camPosTime[3] = time;
// Use debug font to print information about this example. // Use debug font to print information about this example.
bgfx::dbgTextClear(); bgfx::dbgTextClear();
@ -458,53 +680,110 @@ int _main_(int _argc, char** _argv)
bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Image-based lighting."); bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Image-based lighting.");
bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs); bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
float at[3] = { 0.0f, 0.0f, 0.0f }; // Camera.
float eye[3] = { 0.0f, 0.0f, -3.0f }; const bool mouseOverGui = imguiMouseOverArea();
mouse.update(mouseState.m_mx, mouseState.m_my, mouseState.m_mz, width, height);
bx::mtxRotateXY(s_uniforms.m_mtx if (!mouseOverGui)
, 0.0f {
, time if (mouseState.m_buttons[entry::MouseButton::Left])
); {
camera.orbit(mouse.m_dx, mouse.m_dy);
}
else if (mouseState.m_buttons[entry::MouseButton::Right])
{
camera.dolly(mouse.m_dx + mouse.m_dy);
}
else if (mouseState.m_buttons[entry::MouseButton::Middle])
{
settings.m_envRotDest += mouse.m_dx*2.0f;
}
else if (0 != mouse.m_scroll)
{
camera.dolly(float(mouse.m_scroll)*0.05f);
}
}
camera.update(deltaTimeSec);
memcpy(uniforms.m_cameraPos, camera.m_pos.curr, 3*sizeof(float) );
// View Transform 0.
float view[16]; float view[16];
float proj[16]; float proj[16];
bx::mtxIdentity(view); bx::mtxIdentity(view);
bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f); bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
bgfx::setViewTransform(0, view, proj); bgfx::setViewTransform(0, view, proj);
bx::mtxLookAt(view, eye, at); // View Transform 1.
memcpy(s_uniforms.m_camPosTime, eye, 3*sizeof(float) ); camera.mtxLookAt(view);
bx::mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f); bx::mtxProj(proj, 45.0f, float(width)/float(height), 0.1f, 100.0f);
bgfx::setViewTransform(1, view, proj); bgfx::setViewTransform(1, view, proj);
// View rect.
bgfx::setViewRect(0, 0, 0, width, height); bgfx::setViewRect(0, 0, 0, width, height);
bgfx::setViewRect(1, 0, 0, width, height); bgfx::setViewRect(1, 0, 0, width, height);
// View 0. // Env rotation.
const float amount = bx::fmin(deltaTimeSec/0.12f, 1.0f);
settings.m_envRotCurr = bx::flerp(settings.m_envRotCurr, settings.m_envRotDest, amount);
// Env mtx.
float mtxEnvView[16];
camera.envViewMtx(mtxEnvView);
float mtxEnvRot[16];
bx::mtxRotateY(mtxEnvRot, settings.m_envRotCurr);
bx::mtxMul(uniforms.m_mtx, mtxEnvView, mtxEnvRot);
// Submit view 0.
bgfx::setTexture(0, s_texCube, lightProbes[currentLightProbe].m_tex); bgfx::setTexture(0, s_texCube, lightProbes[currentLightProbe].m_tex);
bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE); bgfx::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad( (float)width, (float)height, true); screenSpaceQuad( (float)width, (float)height, true);
s_uniforms.submitPerDrawUniforms(); uniforms.submit();
bgfx::submit(0, programSky); bgfx::submit(0, programSky);
// View 1. // Submit view 1.
float mtx[16]; if (0 == settings.m_meshSelection)
bx::mtxSRT(mtx {
, 1.0f // Submit bunny.
, 1.0f float mtx[16];
, 1.0f bx::mtxSRT(mtx, 1.0f, 1.0f, 1.0f, 0.0f, bx::pi, 0.0f, 0.0f, -0.80f, 0.0f);
, 0.0f bgfx::setTexture(0, s_texCube, lightProbes[currentLightProbe].m_tex);
, bx::pi+time bgfx::setTexture(1, s_texCubeIrr, lightProbes[currentLightProbe].m_texIrr);
, 0.0f meshSubmit(meshBunny, 1, programMesh, mtx);
, 0.0f }
, -1.0f else
, 0.0f {
); // Submit orbs.
for (float yy = 0, yend = 5.0f; yy < yend; yy+=1.0f)
{
for (float xx = 0, xend = 5.0f; xx < xend; xx+=1.0f)
{
const float scale = 1.2f;
const float spacing = 2.2f;
const float yAdj = -0.8f;
bgfx::setTexture(0, s_texCube, lightProbes[currentLightProbe].m_tex); float mtx[16];
bgfx::setTexture(1, s_texCubeIrr, lightProbes[currentLightProbe].m_texIrr); bx::mtxSRT(mtx
meshSubmit(meshBunny, 1, programMesh, mtx); , scale/xend
, scale/xend
, scale/xend
, 0.0f
, 0.0f
, 0.0f
, 0.0f + (xx/xend)*spacing - (1.0f + (scale-1.0f)*0.5f - 1.0f/xend)
, yAdj/yend + (yy/yend)*spacing - (1.0f + (scale-1.0f)*0.5f - 1.0f/yend)
, 0.0f
);
uniforms.m_glossiness = xx*(1.0f/xend);
uniforms.m_reflectivity = (yend-yy)*(1.0f/yend);
uniforms.m_metalOrSpec = 0.0f;
uniforms.submit();
bgfx::setTexture(0, s_texCube, lightProbes[currentLightProbe].m_tex);
bgfx::setTexture(1, s_texCubeIrr, lightProbes[currentLightProbe].m_texIrr);
meshSubmit(meshOrb, 1, programMesh, mtx);
}
}
}
// Advance to next frame. Rendering thread will be kicked to // Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives. // process submitted rendering primitives.
@ -512,6 +791,7 @@ int _main_(int _argc, char** _argv)
} }
meshUnload(meshBunny); meshUnload(meshBunny);
meshUnload(meshOrb);
// Cleanup. // Cleanup.
bgfx::destroyProgram(programMesh); bgfx::destroyProgram(programMesh);
@ -530,7 +810,7 @@ int _main_(int _argc, char** _argv)
lightProbes[ii].destroy(); lightProbes[ii].destroy();
} }
s_uniforms.destroy(); uniforms.destroy();
imguiDestroy(); imguiDestroy();

View file

@ -0,0 +1,28 @@
/*
* Copyright 2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
uniform vec4 u_params[12];
#define u_mtx0 u_params[0]
#define u_mtx1 u_params[1]
#define u_mtx2 u_params[2]
#define u_mtx3 u_params[3]
#define u_glossiness u_params[4].x
#define u_reflectivity u_params[4].y
#define u_exposure u_params[4].z
#define u_bgType u_params[4].w
#define u_metalOrSpec u_params[5].x
#define u_unused u_params[5].yzw
#define u_doDiffuse u_params[6].x
#define u_doSpecular u_params[6].y
#define u_doDiffuseIbl u_params[6].z
#define u_doSpecularIbl u_params[6].w
#define u_camPos u_params[7].xyz
#define u_unused7 u_params[7].w
#define u_rgbDiff u_params[8]
#define u_rgbSpec u_params[9]
#define u_lightDir u_params[10].xyz
#define u_unused10 u_params[10].w
#define u_lightCol u_params[11].xyz
#define u_unused11 u_params[11].w

View file

@ -2,19 +2,19 @@ $input a_position, a_normal
$output v_view, v_normal $output v_view, v_normal
/* /*
* Copyright 2014 Dario Manesku. All rights reserved. * Copyright 2014-2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/ */
#include "../common/common.sh" #include "../common/common.sh"
#include "uniforms.sh"
uniform vec4 u_camPos;
void main() void main()
{ {
gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) ); gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
v_view = u_camPos - mul(u_model[0], vec4(a_position, 1.0)).xyz;
vec3 normal = a_normal * 2.0 - 1.0; vec3 normal = a_normal * 2.0 - 1.0;
v_normal = mul(u_model[0], vec4(normal, 0.0) ).xyz; v_normal = mul(u_model[0], vec4(normal, 0.0) ).xyz;
v_view = normalize(u_camPos.xyz - mul(u_model[0], vec4(a_position, 1.0)).xyz);
} }

View file

@ -2,11 +2,12 @@ $input a_position, a_texcoord0
$output v_dir $output v_dir
/* /*
* Copyright 2014 Dario Manesku. All rights reserved. * Copyright 2014-2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause * License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/ */
#include "../common/common.sh" #include "../common/common.sh"
#include "uniforms.sh"
uniform mat4 u_mtx; uniform mat4 u_mtx;
@ -14,6 +15,15 @@ void main()
{ {
gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) ); gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
vec2 tex = 2.0 * a_texcoord0 - 1.0; float fov = 45.0;
v_dir = mul(u_mtx, vec4(tex, 1.0, 0.0) ).xyz; float height = tan(fov*0.5);
float aspect = height*(4.0/3.0);
vec2 tex = (2.0*a_texcoord0-1.0) * vec2(aspect, height);
mat4 mtx;
mtx[0] = u_mtx0;
mtx[1] = u_mtx1;
mtx[2] = u_mtx2;
mtx[3] = u_mtx3;
v_dir = instMul(mtx, vec4(tex, 1.0, 0.0) ).xyz;
} }

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.