Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add specular-glossiness workflow and some gui for tweaking values #2

Merged
merged 3 commits into from
Nov 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html lang="en">
<head>
<title>glTF PBR Example</title>
Expand Down Expand Up @@ -62,22 +62,63 @@
<!-- Additional Utils -->
<script src="js/Detector.js"></script>
<script src="js/stats.min.js"></script>
<script src="js/dat.gui.min.js"></script>

<script id="fragmentShaderSpecularGlossiness" type="x-shader/x-fragment">
precision highp float;

<script id="fragmentShader" type="x-shader/x-fragment">
uniform vec4 diffuseFactor;
uniform vec3 specularFactor;
uniform float glossinessFactor;

vec4 getDiffuseColor()
{
return diffuseFactor;
}

float getSpecularRoughness()
{
return clamp( 1.0 - glossinessFactor, 0.04, 1.0 );
}

vec3 getSpecularColor()
{
return specularFactor;
}
</script>

<script id="fragmentShaderMetallicRoughness" type="x-shader/x-fragment">
precision highp float;

uniform vec4 baseColorFactor;
uniform float metallicFactor;
uniform float roughnessFactor;
uniform float reflectivityFactor;

vec4 getDiffuseColor()
{
return vec4( vec3( baseColorFactor ) * ( 1.0 - metallicFactor ), baseColorFactor.a );
}

float getSpecularRoughness()
{
return clamp( roughnessFactor, 0.04, 1.0 );
}

vec3 getSpecularColor()
{
float f0 = 0.16 * reflectivityFactor * reflectivityFactor;
return mix( vec3( f0 ), vec3( baseColorFactor ), metallicFactor );
}
</script>

<script id="fragmentShader" type="x-shader/x-fragment">
// Three.js built-in uniforms
//uniform mat4 viewMatrix;
//uniform vec3 cameraPosition;
//uniform float toneMappingExposure;
//uniform float toneMappingWhitePoint;

uniform vec3 diffuse;
uniform float roughness;
uniform float metalness;
uniform float opacity;

uniform sampler2D envMap;

varying vec3 vViewPosition;
Expand All @@ -93,8 +134,6 @@
#define RECIPROCAL_PI2 0.15915494
#define EPSILON 1e-6

#define DEFAULT_SPECULAR_COEFFICIENT 0.04

#define saturate(a) clamp( a, 0.0, 1.0 )


Expand Down Expand Up @@ -336,16 +375,13 @@

// material definition

vec4 diffuseColor = vec4(diffuse, 1.0);
vec4 diffuseColor = getDiffuseColor();

float roughnessFactor = roughness;
float metalnessFactor = metalness;
PhysicalMaterial material;
material.diffuseColor = vec3(diffuseColor);
material.specularRoughness = getSpecularRoughness();
material.specularColor = getSpecularColor();

PhysicalMaterial material;
material.diffuseColor = diffuseColor.rgb * ( 1.0 - metalnessFactor );
material.specularRoughness = clamp( roughnessFactor, 0.04, 1.0 );
material.specularColor = mix( vec3( DEFAULT_SPECULAR_COEFFICIENT ), diffuseColor.rgb, metalnessFactor );


// local geometry definition

Expand Down Expand Up @@ -405,6 +441,14 @@


<script>
var Controls = function () {
this.workflow = 'metallic-roughness';
this.albedo = "#ffffff";
this.opacity = 1.0;
this.reflectivity = 0.5;
}

var controls = new Controls();

if (!Detector.webgl)
{
Expand All @@ -424,6 +468,11 @@

function init()
{
var gui = new dat.GUI();
gui.add(controls, 'workflow', ['metallic-roughness', 'specular-glossiness']).onChange(onWorkflowChange);
gui.addColor(controls, 'albedo').onChange(updatePBRMaterial);
gui.add(controls, 'opacity', 0.0, 1.0).onChange(updatePBRMaterial);
gui.add(controls, 'reflectivity', 0.0, 1.0).onChange(updatePBRMaterial);

container = document.getElementById( 'container' );

Expand All @@ -432,6 +481,7 @@

scene = new THREE.Scene();

/*
var texLoader = new THREE.TextureLoader();
var envTexture = texLoader.load('images/environment_equirect.jpg',
function(texture)
Expand All @@ -440,32 +490,31 @@
texture.wrapT = THREE.RepeatWrapping;
texture.flipY = false;
});
*/


var sphereRadius = 1.0;
var sphereSegments = 64;
const sphereRadius = 1.0;
const sphereSegments = 64;
var sphereGeometry = new THREE.SphereGeometry(sphereRadius, sphereSegments, sphereSegments);

var numSpheresX = 5;
var numSpheresY = 5;

var x, y, sphere, pbrMaterial;
var coordStep = 2.5;
const numSpheresX = 5;
const numSpheresY = 5;
const coordStep = 2.5;

for (y = 0; y < numSpheresY; ++y)
for (x = 0; x < numSpheresX; ++x)
for (var y = 0; y < numSpheresY; ++y)
{
var row = new THREE.Object3D();
for (var x = 0; x < numSpheresX; ++x)
{
pbrMaterial = makePBRMaterial( x / (numSpheresX-1), //roughness
1.0 - y / (numSpheresY-1), //metalness
envTexture);

sphere = new THREE.Mesh(sphereGeometry, pbrMaterial);

var sphere = new THREE.Mesh(sphereGeometry);
sphere.position.x = (x - 0.5 * (numSpheresX-1)) * coordStep;
sphere.position.y = (y - 0.5 * (numSpheresY-1)) * coordStep;

scene.add(sphere);
sphere.position.y = (y - 0.5 * (numSpheresY-1)) * coordStep;
row.add(sphere);
}
scene.add(row);
}

onWorkflowChange(controls.workflow);

//(for comparison only)
/*
Expand Down Expand Up @@ -526,39 +575,73 @@

//

function makePBRMaterial(roughnessVal, metalnessVal, envTexture)
{
var customUniforms =
{

diffuse : { value : new THREE.Vector4(1.0, 1.0, 1.0) },
roughness : { value : roughnessVal },
metalness : { value : metalnessVal },
envMap : { value : envTexture }
};

var pbrMaterial = new THREE.ShaderMaterial(
{
uniforms : customUniforms,
vertexShader : document.getElementById('vertexShader' ).textContent,
fragmentShader : document.getElementById('fragmentShader').textContent
});
function onWorkflowChange(value) {
for (var y = 0; y < scene.children.length; y++) {
var row = scene.children[y];
for (var x = 0; x < row.children.length; x++) {
var sphere = row.children[x];
sphere.material = makePBRMaterial();
}
}

//(for comparison only)
/*
var threePBRMaterial = new THREE.MeshStandardMaterial({
color: 0xFFFFFF,
metalness : metalnessVal,
roughness : roughnessVal
});
updatePBRMaterial();
}

return threePBRMaterial;
*/
//

return pbrMaterial;
function updatePBRMaterial() {
const albedo = new THREE.Vector4(
parseInt(controls.albedo.substring(1, 3), 16) / 255.0,
parseInt(controls.albedo.substring(3, 5), 16) / 255.0,
parseInt(controls.albedo.substring(5, 7), 16) / 255.0,
controls.opacity);

const reflectivity = controls.reflectivity;

for (var y = 0; y < scene.children.length; y++) {
var row = scene.children[y];
for (var x = 0; x < row.children.length; x++) {
var sphere = row.children[x];
var roughness = x / (row.children.length - 1);
var metalness = 1 - y / (scene.children.length - 1);

var customUniforms = sphere.material.uniforms;
if (controls.workflow == 'metallic-roughness') {
customUniforms['baseColorFactor'] = { value: albedo };
customUniforms['metallicFactor'] = { value: metalness };
customUniforms['roughnessFactor'] = { value: roughness };
customUniforms['reflectivityFactor'] = { value: reflectivity };
}
else {
var diffuse = new THREE.Vector3(albedo.x, albedo.y, albedo.z).multiplyScalar(1.0 - metalness);
customUniforms['diffuseFactor'] = { value: new THREE.Vector4(diffuse.x, diffuse.y, diffuse.z, albedo.w) };

var f0 = 0.16 * reflectivity * reflectivity;
customUniforms['specularFactor'] = { value: new THREE.Vector3(f0, f0, f0).lerp(new THREE.Vector3(albedo.x, albedo.y, albedo.z), metalness) };

customUniforms['glossinessFactor'] = { value: 1.0 - roughness };
}
}
}
}

</script>
//

function makePBRMaterial() {
var fragmentShaderId;
if (controls.workflow == 'metallic-roughness') {
fragmentShaderId = 'fragmentShaderMetallicRoughness';
}
else {
fragmentShaderId = 'fragmentShaderSpecularGlossiness';
}

return new THREE.ShaderMaterial({
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById(fragmentShaderId).textContent + document.getElementById('fragmentShader').textContent,
transparent: true
});
}
</script>
</body>
</html>
Loading