Merge pull request #701 from dariomanesku/wf

28-wireframe, geometryc with barycentric and 18-ibl redone with cmft-filtered textures.
This commit is contained in:
Branimir Karadžić 2016-02-28 16:19:22 -08:00
commit 6159afd0d3
41 changed files with 1448 additions and 287 deletions

View file

@ -1,77 +1,124 @@
$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
*/
#include "../common/common.sh"
uniform vec4 u_params;
uniform mat4 u_mtx;
uniform vec4 u_flags;
uniform vec4 u_rgbDiff;
uniform vec4 u_rgbSpec;
#include "uniforms.sh"
SAMPLERCUBE(s_texCube, 0);
SAMPLERCUBE(s_texCubeIrr, 1);
#define u_glossiness u_params.x
#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)
vec3 calcFresnel(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()
{
vec3 light = vec3(0.0, 0.0, -1.0);
vec3 clight = vec3(1.0, 1.0, 1.0);
// Light.
vec3 ld = normalize(u_lightDir);
vec3 clight = u_lightCol;
vec3 v = v_view;
vec3 n = normalize(v_normal);
vec3 l = normalize(light);
vec3 h = normalize(v + l);
// Input.
vec3 nn = normalize(v_normal);
vec3 vv = normalize(v_view);
vec3 hh = normalize(vv + ld);
float ndotl = clamp(dot(n, l), 0.0, 1.0); //diff
float ndoth = clamp(dot(n, h), 0.0, 1.0); //spec
float vdoth = clamp(dot(v, h), 0.0, 1.0); //spec fresnel
float ndotv = clamp(dot(n, v), 0.0, 1.0); //env spec fresnel
float ndotv = clamp(dot(nn, vv), 0.0, 1.0);
float ndotl = clamp(dot(nn, ld), 0.0, 1.0);
float ndoth = clamp(dot(nn, hh), 0.0, 1.0);
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);
vec3 cubeN = normalize(mul(u_mtx, vec4(n, 0.0)).xyz);
// Reflection.
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);
vec3 cenv = textureCubeLod(s_texCube, cubeR, mipLevel).xyz;
// Direct lighting.
vec3 dirSpec = dirF0;
vec3 dirDiff = albedo * 1.0-dirF0;
vec3 kd = u_rgbDiff.xyz;
vec3 ks = u_rgbSpec.xyz;
vec3 lambert = u_doDiffuse * calcLambert(dirDiff, ndotl);
vec3 blinn = u_doSpecular * calcBlinn(dirSpec, ndoth, ndotl, specPwr(gloss));
vec3 direct = (lambert + blinn)*clight;
vec3 cs = ks * u_diffspec;
vec3 cd = kd * (1.0 - cs);
// Indirect lighting.
vec3 envSpec = envF0;
vec3 envDiff = albedo * 1.0-envF0;
vec3 diff = cd;
float pwr = exp2(u_glossiness * 11.0 + 1.0);
vec3 spec = cs * pow(ndoth, pwr) * ( (pwr + 8.0)/8.0) * fresnel(cs, vdoth);
// Note: Environment textures are filtered with cmft: https://github.com/dariomanesku/cmft
// Params used:
// --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;
vec3 ambdiff = cd * textureCube(s_texCubeIrr, cubeN).xyz;
mat4 mtx;
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 ec = (ambdiff * u_doDiffuseIbl + ambspec * u_doSpecularIbl);
vec3 radiance = u_doDiffuseIbl * envSpec * toLinear(textureCubeLod(s_texCube, cubeR, mip).xyz);
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);
gl_FragColor.xyz = toFilmic(color);
gl_FragColor.w = 1.0;
}

View file

@ -1,22 +1,45 @@
$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
*/
#include "../common/common.sh"
#include "uniforms.sh"
SAMPLERCUBE(s_texCube, 0);
SAMPLERCUBE(s_texCubeIrr, 1);
uniform vec4 u_params;
#define u_exposure u_params.y
// 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()
{
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);
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
*/
@ -18,86 +18,51 @@ static float s_texelHalf = 0.0f;
struct Uniforms
{
enum { NumVec4 = 12 };
void init()
{
m_time = 0.0f;
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);
u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, NumVec4);
}
// Call this once per frame.
void submitPerFrameUniforms()
void submit()
{
bgfx::setUniform(u_mtx, m_mtx);
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);
bgfx::setUniform(u_params, m_params, NumVec4);
}
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_mtx);
}
union
{
struct
{
float m_glossiness;
float m_exposure;
float m_diffspec;
float m_time;
union
{
float m_mtx[16];
/* 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_flags;
bgfx::UniformHandle u_camPos;
bgfx::UniformHandle u_rgbDiff;
bgfx::UniformHandle u_rgbSpec;
};
static Uniforms s_uniforms;
struct PosColorTexCoord0Vertex
{
float m_x;
@ -181,11 +146,8 @@ struct LightProbe
{
enum Enum
{
Wells,
Uffizi,
Pisa,
Ennis,
Grace,
Bolonga,
Kyoto,
Count
};
@ -213,6 +175,253 @@ struct LightProbe
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)
{
Args args(_argc, _argv);
@ -240,18 +449,16 @@ int _main_(int _argc, char** _argv)
imguiCreate();
// Uniforms.
s_uniforms.init();
Uniforms uniforms;
uniforms.init();
// Vertex declarations.
PosColorTexCoord0Vertex::init();
LightProbe lightProbes[LightProbe::Count];
lightProbes[LightProbe::Wells ].load("wells");
lightProbes[LightProbe::Uffizi].load("uffizi");
lightProbes[LightProbe::Pisa ].load("pisa");
lightProbes[LightProbe::Ennis ].load("ennis");
lightProbes[LightProbe::Grace ].load("grace");
LightProbe::Enum currentLightProbe = LightProbe::Wells;
lightProbes[LightProbe::Bolonga].load("bolonga");
lightProbes[LightProbe::Kyoto ].load("kyoto");
LightProbe::Enum currentLightProbe = LightProbe::Bolonga;
bgfx::UniformHandle u_mtx = bgfx::createUniform("u_mtx", bgfx::UniformType::Mat4);
bgfx::UniformHandle u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4);
@ -266,43 +473,73 @@ int _main_(int _argc, char** _argv)
Mesh* meshBunny;
meshBunny = meshLoad("meshes/bunny.bin");
Mesh* meshOrb;
meshOrb = meshLoad("meshes/orb.bin");
Camera camera;
Mouse mouse;
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_exposure;
float m_diffspec;
float m_radianceSlider;
float m_bgType;
float m_reflectivity;
float m_rgbDiff[3];
float m_rgbSpec[3];
bool m_diffuse;
bool m_specular;
bool m_diffuseIbl;
bool m_specularIbl;
float m_lod;
bool m_doDiffuse;
bool m_doSpecular;
bool m_doDiffuseIbl;
bool m_doSpecularIbl;
bool m_showLightColorWheel;
bool m_showDiffColorWheel;
bool m_showSpecColorWheel;
uint8_t m_metalOrSpec;
uint8_t m_meshSelection;
ImguiCubemap::Enum m_crossCubemapPreview;
};
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;
@ -320,127 +557,114 @@ int _main_(int _argc, char** _argv)
);
static int32_t rightScrollArea = 0;
imguiBeginScrollArea("Settings", width - 256 - 10, 10, 256, 540, &rightScrollArea);
imguiBeginScrollArea("", width - 256 - 10, 10, 256, 700, &rightScrollArea);
imguiLabel("Shade:");
imguiSeparator();
imguiBool("Diffuse", settings.m_diffuse);
imguiBool("Specular", settings.m_specular);
imguiBool("IBL Diffuse", settings.m_diffuseIbl);
imguiBool("IBL Specular", settings.m_specularIbl);
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"
imguiLabel("Environment light:");
imguiIndent();
imguiBool("IBL Diffuse", settings.m_doDiffuseIbl);
imguiBool("IBL Specular", settings.m_doSpecularIbl);
currentLightProbe = LightProbe::Enum(imguiTabs(currentLightProbe, true, ImguiAlign::LeftIndented, 16, 2, 2
, "Bolonga"
, "Kyoto"
) );
static float lod = 0.0f;
if (imguiCube(lightProbes[currentLightProbe].m_tex, lod, settings.m_crossCubemapPreview, true) )
if (imguiCube(lightProbes[currentLightProbe].m_tex, settings.m_lod, settings.m_crossCubemapPreview, true) )
{
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();
imguiBeginScrollArea("Settings", 10, 70, 256, 576, &leftScrollArea);
imguiBeginScrollArea("", 10, 70, 256, 636, &leftScrollArea);
imguiLabel("Material properties:");
imguiSeparator();
imguiSlider("Diffuse - Specular", settings.m_diffspec, 0.0f, 1.0f, 0.01f);
imguiSlider("Glossiness" , settings.m_glossiness, 0.0f, 1.0f, 0.01f);
imguiSeparator();
imguiLabel("Mesh:");
imguiIndent();
settings.m_meshSelection = imguiChoose(settings.m_meshSelection, "Bunny", "Orbs");
imguiUnindent();
imguiColorWheel("Diffuse color:", &settings.m_rgbDiff[0], settings.m_showDiffColorWheel);
imguiSeparator();
imguiColorWheel("Specular color:", &settings.m_rgbSpec[0], settings.m_showSpecColorWheel);
imguiSeparator();
imguiLabel("Predefined materials:");
imguiSeparator();
if (imguiButton("Gold") )
const bool isBunny = (0 == settings.m_meshSelection);
if (!isBunny)
{
settings.m_glossiness = 0.8f;
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;
settings.m_metalOrSpec = 0.0f;
}
if (imguiButton("Copper") )
{
settings.m_glossiness = 0.67f;
settings.m_diffspec = 1.0f;
imguiSeparator(4);
imguiLabel("Workflow:");
imguiIndent();
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;
settings.m_rgbDiff[1] = 0.0f;
settings.m_rgbDiff[2] = 0.0f;
imguiSeparator(4);
imguiLabel("Material:");
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;
settings.m_rgbSpec[1] = 0.82f;
settings.m_rgbSpec[2] = 0.76f;
}
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;
}
imguiColorWheel("Diffuse:", &settings.m_rgbDiff[0], settings.m_showDiffColorWheel, 0.7f);
imguiSeparator();
imguiColorWheel("Specular:", &settings.m_rgbSpec[0], settings.m_showSpecColorWheel, 0.7f, (1 == settings.m_metalOrSpec) && isBunny);
imguiEndScrollArea();
imguiEndFrame();
s_uniforms.m_glossiness = settings.m_glossiness;
s_uniforms.m_exposure = settings.m_exposure;
s_uniforms.m_diffspec = settings.m_diffspec;
s_uniforms.m_flags[0] = float(settings.m_diffuse);
s_uniforms.m_flags[1] = float(settings.m_specular);
s_uniforms.m_flags[2] = float(settings.m_diffuseIbl);
s_uniforms.m_flags[3] = float(settings.m_specularIbl);
memcpy(s_uniforms.m_rgbDiff, settings.m_rgbDiff, 3*sizeof(float) );
memcpy(s_uniforms.m_rgbSpec, settings.m_rgbSpec, 3*sizeof(float) );
s_uniforms.submitPerFrameUniforms();
uniforms.m_glossiness = settings.m_glossiness;
uniforms.m_reflectivity = settings.m_reflectivity;
uniforms.m_exposure = settings.m_exposure;
uniforms.m_bgType = settings.m_bgType;
uniforms.m_metalOrSpec = float(settings.m_metalOrSpec);
uniforms.m_doDiffuse = float(settings.m_doDiffuse);
uniforms.m_doSpecular = float(settings.m_doSpecular);
uniforms.m_doDiffuseIbl = float(settings.m_doDiffuseIbl);
uniforms.m_doSpecularIbl = float(settings.m_doSpecularIbl);
memcpy(uniforms.m_rgbDiff, settings.m_rgbDiff, 3*sizeof(float) );
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();
static int64_t last = now;
@ -448,9 +672,7 @@ int _main_(int _argc, char** _argv)
last = now;
const double freq = double(bx::getHPFrequency() );
const double toMs = 1000.0/freq;
time += (float)(frameTime*settings.m_speed/freq);
s_uniforms.m_camPosTime[3] = time;
const double deltaTimeSec = double(frameTime)/freq;
// Use debug font to print information about this example.
bgfx::dbgTextClear();
@ -458,53 +680,110 @@ int _main_(int _argc, char** _argv)
bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Image-based lighting.");
bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
float at[3] = { 0.0f, 0.0f, 0.0f };
float eye[3] = { 0.0f, 0.0f, -3.0f };
bx::mtxRotateXY(s_uniforms.m_mtx
, 0.0f
, time
);
// Camera.
const bool mouseOverGui = imguiMouseOverArea();
mouse.update(mouseState.m_mx, mouseState.m_my, mouseState.m_mz, width, height);
if (!mouseOverGui)
{
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 proj[16];
bx::mtxIdentity(view);
bx::mtxOrtho(proj, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 100.0f);
bgfx::setViewTransform(0, view, proj);
bx::mtxLookAt(view, eye, at);
memcpy(s_uniforms.m_camPosTime, eye, 3*sizeof(float) );
bx::mtxProj(proj, 60.0f, float(width)/float(height), 0.1f, 100.0f);
// View Transform 1.
camera.mtxLookAt(view);
bx::mtxProj(proj, 45.0f, float(width)/float(height), 0.1f, 100.0f);
bgfx::setViewTransform(1, view, proj);
// View rect.
bgfx::setViewRect(0, 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::setState(BGFX_STATE_RGB_WRITE|BGFX_STATE_ALPHA_WRITE);
screenSpaceQuad( (float)width, (float)height, true);
s_uniforms.submitPerDrawUniforms();
uniforms.submit();
bgfx::submit(0, programSky);
// View 1.
float mtx[16];
bx::mtxSRT(mtx
, 1.0f
, 1.0f
, 1.0f
, 0.0f
, bx::pi+time
, 0.0f
, 0.0f
, -1.0f
, 0.0f
);
// Submit view 1.
if (0 == settings.m_meshSelection)
{
// Submit bunny.
float mtx[16];
bx::mtxSRT(mtx, 1.0f, 1.0f, 1.0f, 0.0f, bx::pi, 0.0f, 0.0f, -0.80f, 0.0f);
bgfx::setTexture(0, s_texCube, lightProbes[currentLightProbe].m_tex);
bgfx::setTexture(1, s_texCubeIrr, lightProbes[currentLightProbe].m_texIrr);
meshSubmit(meshBunny, 1, programMesh, mtx);
}
else
{
// 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);
bgfx::setTexture(1, s_texCubeIrr, lightProbes[currentLightProbe].m_texIrr);
meshSubmit(meshBunny, 1, programMesh, mtx);
float mtx[16];
bx::mtxSRT(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
// process submitted rendering primitives.
@ -512,6 +791,7 @@ int _main_(int _argc, char** _argv)
}
meshUnload(meshBunny);
meshUnload(meshOrb);
// Cleanup.
bgfx::destroyProgram(programMesh);
@ -530,7 +810,7 @@ int _main_(int _argc, char** _argv)
lightProbes[ii].destroy();
}
s_uniforms.destroy();
uniforms.destroy();
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
/*
* 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
*/
#include "../common/common.sh"
uniform vec4 u_camPos;
#include "uniforms.sh"
void main()
{
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;
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
/*
* 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
*/
#include "../common/common.sh"
#include "uniforms.sh"
uniform mat4 u_mtx;
@ -14,6 +15,15 @@ void main()
{
gl_Position = mul(u_modelViewProj, vec4(a_position, 1.0) );
vec2 tex = 2.0 * a_texcoord0 - 1.0;
v_dir = mul(u_mtx, vec4(tex, 1.0, 0.0) ).xyz;
float fov = 45.0;
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;
}

View file

@ -0,0 +1,78 @@
$input v_view, v_bc, v_normal
/*
* Copyright 2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include "../common/common.sh"
#include "uniforms.sh"
const vec3 shEnv[9] = vec3[9](vec3( 0.967757057878229854, 0.976516067990363390, 0.891218272348969998) /* Band 0 */
, vec3(-0.384163503608655643, -0.423492289131209787, -0.425532726148547868) /* Band 1 */
, vec3( 0.055906294587354334, 0.056627436881069373, 0.069969936396987467)
, vec3( 0.120985157386215209, 0.119297994074027414, 0.117111965829213599)
, vec3(-0.176711633774331106, -0.170331404095516392, -0.151345020570876621) /* Band 2 */
, vec3(-0.124682114349692147, -0.119340785411183953, -0.096300354204368860)
, vec3( 0.001852378550138503, -0.032592784164597745, -0.088204495001329680)
, vec3( 0.296365482782109446, 0.281268696656263029, 0.243328223888495510)
, vec3(-0.079826665303240341, -0.109340956251195970, -0.157208859664677764)
);
vec3 evalSh(vec3 _dir)
{
# define k01 0.2820947918 // sqrt( 1/PI)/2
# define k02 0.4886025119 // sqrt( 3/PI)/2
# define k03 1.0925484306 // sqrt(15/PI)/2
# define k04 0.3153915652 // sqrt( 5/PI)/4
# define k05 0.5462742153 // sqrt(15/PI)/4
vec3 nn = _dir.zxy;
float sh[9];
sh[0] = k01;
sh[1] = -k02*nn.y;
sh[2] = k02*nn.z;
sh[3] = -k02*nn.x;
sh[4] = k03*nn.y*nn.x;
sh[5] = -k03*nn.y*nn.z;
sh[6] = k04*(3.0*nn.z*nn.z-1.0);
sh[7] = -k03*nn.x*nn.z;
sh[8] = k05*(nn.x*nn.x-nn.y*nn.y);
vec3 rgb = vec3_splat(0.0);
rgb += shEnv[0] * sh[0] * 1.0;
rgb += shEnv[1] * sh[1] * 2.0/2.5;
rgb += shEnv[2] * sh[2] * 2.0/2.5;
rgb += shEnv[3] * sh[3] * 2.0/2.5;
rgb += shEnv[4] * sh[4] * 1.0/2.5;
rgb += shEnv[5] * sh[5] * 0.5;
rgb += shEnv[6] * sh[6] * 0.5;
rgb += shEnv[7] * sh[7] * 0.5;
rgb += shEnv[8] * sh[8] * 0.5;
return rgb;
}
void main()
{
vec3 nn = normalize(v_normal);
vec3 col = evalSh(nn);
if (0.0 != u_drawEdges)
{
vec3 wfColor = u_wfColor;
float wfOpacity = u_wfOpacity;
float thickness = u_wfThickness;
vec3 fw = abs(dFdx(v_bc)) + abs(dFdy(v_bc));
vec3 val = smoothstep(vec3_splat(0.0), vec3_splat(fw*thickness), v_bc);
float edge = min(min(val.x, val.y), val.z); // Gets to 0.0 when close to edges.
vec3 edgeCol = mix(col, wfColor, wfOpacity);
col = mix(edgeCol, col, edge);
}
gl_FragColor.xyz = col;
gl_FragColor.w = 1.0;
}

View file

@ -0,0 +1,26 @@
$input v_view, v_bc
/*
* Copyright 2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include "../common/common.sh"
#include "uniforms.sh"
void main()
{
vec3 color = u_wfColor;
float opacity = u_wfOpacity;
float thickness = u_wfThickness;
if (!gl_FrontFacing) { opacity *= 0.5; }
vec3 fw = abs(dFdx(v_bc)) + abs(dFdy(v_bc));
vec3 val = smoothstep(vec3_splat(0.0), vec3_splat(fw*thickness), v_bc);
float edge = min(min(val.x, val.y), val.z); // Gets to 0.0 around the edges.
vec4 rgba = vec4(color, (1.0-edge)*opacity);
gl_FragColor = rgba;
}

View file

@ -0,0 +1,17 @@
#
# Copyright 2011-2016 Branimir Karadzic. All rights reserved.
# License: http://www.opensource.org/licenses/BSD-2-Clause
#
BGFX_DIR=../..
RUNTIME_DIR=$(BGFX_DIR)/examples/runtime
BUILD_DIR=../../.build
include $(BGFX_DIR)/scripts/shader.mk
rebuild:
@make -s --no-print-directory TARGET=0 clean all
@make -s --no-print-directory TARGET=1 clean all
@make -s --no-print-directory TARGET=2 clean all
@make -s --no-print-directory TARGET=3 clean all
@make -s --no-print-directory TARGET=4 clean all

View file

@ -0,0 +1,12 @@
/*
* Copyright 2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
uniform vec4 u_params[3];
#define u_camPos u_params[0].xyz
#define u_unused0 u_params[0].w
#define u_wfColor u_params[1].xyz
#define u_wfOpacity u_params[1].w
#define u_drawEdges u_params[2].x
#define u_wfThickness u_params[2].y

View file

@ -0,0 +1,7 @@
vec3 v_view : TEXCOORD0 = vec3(0.0, 0.0, 0.0);
vec3 v_bc : TEXCOORD1 = vec3(0.0, 0.0, 0.0);
vec3 v_normal : NORMAL = vec3(0.0, 0.0, 1.0);
vec3 a_position : POSITION;
vec3 a_color1 : COLOR1;
vec3 a_normal : NORMAL;

View file

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

View file

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

View file

@ -0,0 +1,564 @@
/*
* Copyright 2016 Dario Manesku. All rights reserved.
* License: https://github.com/bkaradzic/bgfx#license-bsd-2-clause
*/
#include "common.h"
#include "bgfx_utils.h"
#include "imgui/imgui.h"
class Wireframe : public entry::AppI
{
struct DrawMode
{
enum
{
WireframeShaded,
Wireframe,
Shaded,
};
};
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] = -2.0f;
m_pos.dest[0] = 0.0f;
m_pos.dest[1] = 0.0f;
m_pos.dest[2] = -2.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 = 0.01f;
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);
}
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;
};
struct MeshMtx
{
MeshMtx()
{
m_mesh = NULL;
}
void init(const char* _path
, float _scale = 1.0f
, float _rotX = 0.0f
, float _rotY = 0.0f
, float _rotZ = 0.0f
, float _transX = 0.0f
, float _transY = 0.0f
, float _transZ = 0.0f
)
{
m_mesh = meshLoad(_path);
bx::mtxSRT(m_mtx
, _scale
, _scale
, _scale
, _rotX
, _rotY
, _rotZ
, _transX
, _transY
, _transZ
);
}
void destroy()
{
if (NULL != m_mesh)
{
meshUnload(m_mesh);
}
}
Mesh* m_mesh;
float m_mtx[16];
};
struct Uniforms
{
enum { NumVec4 = 3 };
void init()
{
m_camPos[0] = 0.0f;
m_camPos[1] = 1.0f;
m_camPos[2] = -2.5f;
m_wfColor[0] = 1.0f;
m_wfColor[1] = 0.0f;
m_wfColor[2] = 0.0f;
m_wfOpacity = 0.7f;
m_drawEdges = 0.0f;
m_wfThickness = 1.5f;
u_params = bgfx::createUniform("u_params", bgfx::UniformType::Vec4, NumVec4);
}
void submit()
{
bgfx::setUniform(u_params, m_params, NumVec4);
}
void destroy()
{
bgfx::destroyUniform(u_params);
}
union
{
struct
{
/*0*/struct { float m_camPos[3], m_unused0; };
/*1*/struct { float m_wfColor[3], m_wfOpacity; };
/*2*/struct { float m_drawEdges, m_wfThickness, m_unused2[2]; };
};
float m_params[NumVec4*4];
};
bgfx::UniformHandle u_params;
};
void init(int _argc, char** _argv) BX_OVERRIDE
{
Args args(_argc, _argv);
m_width = 1280;
m_height = 720;
m_debug = BGFX_DEBUG_TEXT;
m_reset = BGFX_RESET_VSYNC;
bgfx::init(args.m_type, args.m_pciId);
bgfx::reset(m_width, m_height, m_reset);
// Enable m_debug text.
bgfx::setDebug(m_debug);
// Set view 0 clear state.
bgfx::setViewClear(0
, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH
, 0x303030ff
, 1.0f
, 0
);
m_wfProgram = loadProgram("vs_wf_wireframe", "fs_wf_wireframe");
m_meshProgram = loadProgram("vs_wf_mesh", "fs_wf_mesh");
m_uniforms.init();
m_meshes[0].init("meshes/bunny.bin", 1.0f, 0.0f, bx::pi, 0.0f, 0.0f, -0.8f, 0.0f);
m_meshes[1].init("meshes/hollowcube.bin", 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
m_meshes[2].init("meshes/orb.bin", 1.2f, 0.0f, 0.0f, 0.0f, 0.0f, -0.65f, 0.0f);
// Imgui.
imguiCreate();
m_oldWidth = 0;
m_oldHeight = 0;
m_oldReset = m_reset;
m_meshSelection = 1;
m_drawMode = DrawMode::WireframeShaded;
m_scrollArea = 0;
m_showWfColor = true;
}
virtual int shutdown() BX_OVERRIDE
{
// Cleanup.
imguiDestroy();
m_meshes[0].destroy();
m_meshes[1].destroy();
m_meshes[2].destroy();
bgfx::destroyProgram(m_wfProgram);
bgfx::destroyProgram(m_meshProgram);
m_uniforms.destroy();
// Shutdown bgfx.
bgfx::shutdown();
return 0;
}
bool update() BX_OVERRIDE
{
if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
{
if (m_oldWidth != m_width
|| m_oldHeight != m_height
|| m_oldReset != m_reset)
{
// Recreate variable size render targets when resolution changes.
m_oldWidth = m_width;
m_oldHeight = m_height;
m_oldReset = m_reset;
}
imguiBeginFrame(m_mouseState.m_mx
, m_mouseState.m_my
, (m_mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
| (m_mouseState.m_buttons[entry::MouseButton::Right ] ? IMGUI_MBUT_RIGHT : 0)
| (m_mouseState.m_buttons[entry::MouseButton::Middle] ? IMGUI_MBUT_MIDDLE : 0)
, m_mouseState.m_mz
, m_width
, m_height
);
imguiBeginScrollArea("Settings"
, m_width - m_width / 5 - 10
, 10
, m_width / 5
, 492
, &m_scrollArea
);
imguiSeparatorLine(1); imguiIndent(8); imguiLabel("Draw mode:"); imguiUnindent(8); imguiSeparatorLine(1);
imguiSeparator(4);
{
imguiIndent();
m_drawMode = imguiChoose(m_drawMode
, "Wireframe + Shaded"
, "Wireframe"
, "Shaded"
);
imguiUnindent();
}
imguiSeparator(8);
const bool wfEnabled = (DrawMode::Shaded != m_drawMode);
imguiSeparatorLine(1); imguiIndent(8); imguiLabel("Wireframe:", wfEnabled); imguiUnindent(8); imguiSeparatorLine(1);
imguiSeparator(4);
{
imguiColorWheel("Color", m_uniforms.m_wfColor, m_showWfColor, 0.6f, wfEnabled);
imguiIndent();
imguiSlider("Opacity", m_uniforms.m_wfOpacity, 0.1f, 1.0f, 0.1f, wfEnabled);
imguiSlider("Thickness", m_uniforms.m_wfThickness, 0.6f, 2.2f, 0.1f, wfEnabled);
imguiUnindent();
}
imguiSeparator(8);
imguiSeparatorLine(1); imguiIndent(8); imguiLabel("Mesh:"); imguiUnindent(8); imguiSeparatorLine(1);
imguiSeparator(4);
{
imguiIndent();
const uint32_t prevMeshSel = m_meshSelection;
m_meshSelection = imguiChoose(m_meshSelection
, "Bunny"
, "Orb"
, "Hollowcubes"
);
if (prevMeshSel != m_meshSelection)
{
m_camera.reset();
}
imguiUnindent();
}
imguiSeparator(8);
imguiEndScrollArea();
imguiEndFrame();
// This dummy draw call is here to make sure that view 0 is cleared
// if no other draw calls are submitted to view 0.
bgfx::touch(0);
int64_t now = bx::getHPCounter();
static int64_t last = now;
const int64_t frameTime = now - last;
last = now;
const double freq = double(bx::getHPFrequency() );
const double toMs = 1000.0/freq;
const double deltaTimeSec = double(frameTime)/freq;
// Use m_debug font to print information about this example.
bgfx::dbgTextClear();
bgfx::dbgTextPrintf(0, 1, 0x4f, "bgfx/examples/28-wirefame");
bgfx::dbgTextPrintf(0, 2, 0x6f, "Description: Drawing wireframe mesh.");
bgfx::dbgTextPrintf(0, 3, 0x0f, "Frame: % 7.3f[ms]", double(frameTime)*toMs);
// Setup view.
bgfx::setViewRect(0, 0, 0, bgfx::BackbufferRatio::Equal);
bgfx::setViewClear(0, BGFX_CLEAR_COLOR|BGFX_CLEAR_DEPTH, 0x303030ff, 1.0f, 0);
const bool mouseOverGui = imguiMouseOverArea();
m_mouse.update(m_mouseState.m_mx, m_mouseState.m_my, m_mouseState.m_mz, m_width, m_height);
if (!mouseOverGui)
{
if (m_mouseState.m_buttons[entry::MouseButton::Left])
{
m_camera.orbit(m_mouse.m_dx, m_mouse.m_dy);
}
else if (m_mouseState.m_buttons[entry::MouseButton::Right])
{
m_camera.dolly(m_mouse.m_dx + m_mouse.m_dy);
}
else if (0 != m_mouse.m_scroll)
{
m_camera.dolly(float(m_mouse.m_scroll)*0.1f);
}
}
float view[16];
float proj[16];
m_camera.update(deltaTimeSec);
memcpy(m_uniforms.m_camPos, m_camera.m_pos.curr, 3*sizeof(float));
m_camera.mtxLookAt(view);
bx::mtxProj(proj, 60.0f, float(m_width)/float(m_height), 0.1f, 100.0f);
bgfx::setViewTransform(0, view, proj);
m_uniforms.m_drawEdges = (DrawMode::WireframeShaded == m_drawMode) ? 1.0f : 0.0;
m_uniforms.submit();
if (DrawMode::Wireframe == m_drawMode)
{
uint64_t state = 0
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
| BGFX_STATE_BLEND_FUNC(BGFX_STATE_BLEND_SRC_ALPHA, BGFX_STATE_BLEND_INV_SRC_ALPHA)
;
meshSubmit(m_meshes[m_meshSelection].m_mesh, 0, m_wfProgram, m_meshes[m_meshSelection].m_mtx, state);
}
else
{
uint64_t state = 0
| BGFX_STATE_RGB_WRITE
| BGFX_STATE_ALPHA_WRITE
| BGFX_STATE_DEPTH_TEST_LESS
| BGFX_STATE_DEPTH_WRITE
| BGFX_STATE_CULL_CCW
| BGFX_STATE_MSAA
;
meshSubmit(m_meshes[m_meshSelection].m_mesh, 0, m_meshProgram, m_meshes[m_meshSelection].m_mtx, state);
}
// Advance to next frame. Rendering thread will be kicked to
// process submitted rendering primitives.
bgfx::frame();
return true;
}
return false;
}
entry::MouseState m_mouseState;
bgfx::ProgramHandle m_wfProgram;
bgfx::ProgramHandle m_meshProgram;
uint32_t m_width;
uint32_t m_height;
uint32_t m_debug;
uint32_t m_reset;
uint32_t m_lumBgra8;
uint32_t m_oldWidth;
uint32_t m_oldHeight;
uint32_t m_oldReset;
Camera m_camera;
Mouse m_mouse;
Uniforms m_uniforms;
MeshMtx m_meshes[3];
uint32_t m_meshSelection;
uint32_t m_drawMode; // Holds data for 'DrawMode'.
bool m_showWfColor;
int32_t m_scrollArea;
};
ENTRY_IMPLEMENT_MAIN(Wireframe);

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -420,6 +420,7 @@ exampleProject("23-vectordisplay")
exampleProject("24-nbody")
exampleProject("26-occlusion")
exampleProject("27-terrain")
exampleProject("28-wireframe")
-- C99 source doesn't compile under WinRT settings
if not premake.vstudio.iswinrt() then

View file

@ -81,6 +81,7 @@ struct Index3
int32_t m_texcoord;
int32_t m_normal;
int32_t m_vertexIndex;
int32_t m_vbc; // Barycentric ID. Holds eigher 0, 1 or 2.
};
typedef stl::unordered_map<uint64_t, Index3> Index3Map;
@ -387,6 +388,7 @@ void help(const char* _error = NULL)
" 0 - unpacked 8 bytes (default).\n"
" 1 - packed 4 bytes.\n"
" --tangent Calculate tangent vectors (packing mode is the same as normal).\n"
" --barycentric Adds barycentric vertex attribute (packed in bgfx::Attrib::Color1).\n"
" -c, --compress Compress indices.\n"
"\n"
@ -450,6 +452,7 @@ int main(int _argc, const char* _argv[])
bool ccw = cmdLine.hasArg("ccw");
bool flipV = cmdLine.hasArg("flipv");
bool hasTangent = cmdLine.hasArg("tangent");
bool hasBc = cmdLine.hasArg("barycentric");
FILE* file = fopen(filePath, "r");
if (NULL == file)
@ -513,6 +516,14 @@ int main(int _argc, const char* _argv[])
index.m_texcoord = -1;
index.m_normal = -1;
index.m_vertexIndex = -1;
if (hasBc)
{
index.m_vbc = edge < 3 ? edge : (1+(edge+1) )&1;
}
else
{
index.m_vbc = 0;
}
char* vertex = argv[edge+1];
char* texcoord = strchr(vertex, '/');
@ -542,7 +553,8 @@ int main(int _argc, const char* _argv[])
uint64_t hash0 = index.m_position;
uint64_t hash1 = uint64_t(index.m_texcoord)<<20;
uint64_t hash2 = uint64_t(index.m_normal)<<40;
uint64_t hash = hash0^hash1^hash2;
uint64_t hash3 = uint64_t(index.m_vbc)<<60;
uint64_t hash = hash0^hash1^hash2^hash3;
stl::pair<Index3Map::iterator, bool> result = indexMap.insert(stl::make_pair(hash, index) );
if (!result.second)
@ -755,6 +767,11 @@ int main(int _argc, const char* _argv[])
decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true);
}
if (hasBc)
{
decl.add(bgfx::Attrib::Color1, 4, bgfx::AttribType::Uint8, true);
}
if (hasTexcoord)
{
switch (packUv)
@ -914,6 +931,17 @@ int main(int _argc, const char* _argv[])
*color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff);
}
if (hasBc)
{
const float bc[3] =
{
(index.m_vbc == 0) ? 1.0f : 0.0f,
(index.m_vbc == 1) ? 1.0f : 0.0f,
(index.m_vbc == 2) ? 1.0f : 0.0f,
};
bgfx::vertexPack(bc, true, bgfx::Attrib::Color1, decl, vertices);
}
if (hasTexcoord)
{
float uv[2];