Using WebGLRenderer with logarithmicDepthBufferset option set to true together with ShaderMaterial
I use the following ShaderMaterial
for my objects in scene. The code below is working. However, if I set the WebGLRenderer option logarithmicDepthBuffer
to true
, the Material defined below is not displayed correctly.
new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}`,
fragmentShader: `
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
}`,
side: THREE.DoubleSide,
});
After looking for a solution to this problem, I found the following SO answer. Summarizing, the solution is to add 4 pieces of code to vertexShader
and fragmentShader
.
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
I tried various "positions" but I always got WebGL errors.
THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:63: 'EPSILON' : undeclared identifier
UPDATE added playground: https://codepen.io/anon/pen/gQoaye
If you add the option of logarithmicDepthBuffer
to the constructor, you will see that the ShaderMaterial
won't work anymore.
var renderer = new THREE.WebGLRenderer(logarithmicDepthBuffer:true);
three.js glsl
add a comment |
I use the following ShaderMaterial
for my objects in scene. The code below is working. However, if I set the WebGLRenderer option logarithmicDepthBuffer
to true
, the Material defined below is not displayed correctly.
new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}`,
fragmentShader: `
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
}`,
side: THREE.DoubleSide,
});
After looking for a solution to this problem, I found the following SO answer. Summarizing, the solution is to add 4 pieces of code to vertexShader
and fragmentShader
.
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
I tried various "positions" but I always got WebGL errors.
THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:63: 'EPSILON' : undeclared identifier
UPDATE added playground: https://codepen.io/anon/pen/gQoaye
If you add the option of logarithmicDepthBuffer
to the constructor, you will see that the ShaderMaterial
won't work anymore.
var renderer = new THREE.WebGLRenderer(logarithmicDepthBuffer:true);
three.js glsl
add a comment |
I use the following ShaderMaterial
for my objects in scene. The code below is working. However, if I set the WebGLRenderer option logarithmicDepthBuffer
to true
, the Material defined below is not displayed correctly.
new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}`,
fragmentShader: `
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
}`,
side: THREE.DoubleSide,
});
After looking for a solution to this problem, I found the following SO answer. Summarizing, the solution is to add 4 pieces of code to vertexShader
and fragmentShader
.
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
I tried various "positions" but I always got WebGL errors.
THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:63: 'EPSILON' : undeclared identifier
UPDATE added playground: https://codepen.io/anon/pen/gQoaye
If you add the option of logarithmicDepthBuffer
to the constructor, you will see that the ShaderMaterial
won't work anymore.
var renderer = new THREE.WebGLRenderer(logarithmicDepthBuffer:true);
three.js glsl
I use the following ShaderMaterial
for my objects in scene. The code below is working. However, if I set the WebGLRenderer option logarithmicDepthBuffer
to true
, the Material defined below is not displayed correctly.
new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}`,
fragmentShader: `
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
}`,
side: THREE.DoubleSide,
});
After looking for a solution to this problem, I found the following SO answer. Summarizing, the solution is to add 4 pieces of code to vertexShader
and fragmentShader
.
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
I tried various "positions" but I always got WebGL errors.
THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:63: 'EPSILON' : undeclared identifier
UPDATE added playground: https://codepen.io/anon/pen/gQoaye
If you add the option of logarithmicDepthBuffer
to the constructor, you will see that the ShaderMaterial
won't work anymore.
var renderer = new THREE.WebGLRenderer(logarithmicDepthBuffer:true);
three.js glsl
three.js glsl
edited Nov 26 '18 at 13:13
Rabbid76
39.1k123250
39.1k123250
asked Nov 20 '18 at 10:46
d4rtyd4rty
1,37821533
1,37821533
add a comment |
add a comment |
2 Answers
2
active
oldest
votes
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
In the vertex shader you have to define EPSILON
.
After adding the code snipptes logdepthbuf_pars_vertex.glsl and logdepthbuf_vertex.glsl, the final vertex shader is:
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}
After adding the code snippets, the final fragment shader is:
#ifdef USE_LOGDEPTHBUF
uniform float logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}
See the example:
(function onLoad() {
var container, camera, scene, renderer, orbitControls;
function createModel() {
var material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}`,
fragmentShader: `
#ifdef USE_LOGDEPTHBUF
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}`,
side: THREE.DoubleSide,
});
//var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1, -2);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
orbitControls = new THREE.OrbitControls(camera);
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
createModel();
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
init();
animate();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
add a comment |
I assume you have tried inserting that code in your two shaders? To my understanding, that should be correct.
The error appears to be complaining about the shader not compiling, due to a reference to EPSILON
in the vertex shader body, although EPSILON
was never declared.
Try defining EPSILON
, e.g. using a macro in the shader itself:
#define EPSILON 1e-6
or pass it to the shader as a uniform. (Notice that this is just an example value; you may want to research what a suitable value for EPSILON
might be in your particular case.)
Unfortunately this will lead to a new error:THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:56: 'endifvarying' : invalid directive name ERROR: 0:57: 'gl_Position' : syntax error
– d4rty
Nov 20 '18 at 15:53
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53391303%2fusing-webglrenderer-with-logarithmicdepthbufferset-option-set-to-true-together-w%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
In the vertex shader you have to define EPSILON
.
After adding the code snipptes logdepthbuf_pars_vertex.glsl and logdepthbuf_vertex.glsl, the final vertex shader is:
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}
After adding the code snippets, the final fragment shader is:
#ifdef USE_LOGDEPTHBUF
uniform float logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}
See the example:
(function onLoad() {
var container, camera, scene, renderer, orbitControls;
function createModel() {
var material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}`,
fragmentShader: `
#ifdef USE_LOGDEPTHBUF
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}`,
side: THREE.DoubleSide,
});
//var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1, -2);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
orbitControls = new THREE.OrbitControls(camera);
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
createModel();
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
init();
animate();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
add a comment |
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
In the vertex shader you have to define EPSILON
.
After adding the code snipptes logdepthbuf_pars_vertex.glsl and logdepthbuf_vertex.glsl, the final vertex shader is:
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}
After adding the code snippets, the final fragment shader is:
#ifdef USE_LOGDEPTHBUF
uniform float logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}
See the example:
(function onLoad() {
var container, camera, scene, renderer, orbitControls;
function createModel() {
var material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}`,
fragmentShader: `
#ifdef USE_LOGDEPTHBUF
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}`,
side: THREE.DoubleSide,
});
//var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1, -2);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
orbitControls = new THREE.OrbitControls(camera);
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
createModel();
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
init();
animate();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
add a comment |
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
In the vertex shader you have to define EPSILON
.
After adding the code snipptes logdepthbuf_pars_vertex.glsl and logdepthbuf_vertex.glsl, the final vertex shader is:
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}
After adding the code snippets, the final fragment shader is:
#ifdef USE_LOGDEPTHBUF
uniform float logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}
See the example:
(function onLoad() {
var container, camera, scene, renderer, orbitControls;
function createModel() {
var material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}`,
fragmentShader: `
#ifdef USE_LOGDEPTHBUF
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}`,
side: THREE.DoubleSide,
});
//var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1, -2);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
orbitControls = new THREE.OrbitControls(camera);
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
createModel();
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
init();
animate();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
Where exactly do I have to integrate the provided code snippets, i.e. Vertex shader body and Fragment shader body?
In the vertex shader you have to define EPSILON
.
After adding the code snipptes logdepthbuf_pars_vertex.glsl and logdepthbuf_vertex.glsl, the final vertex shader is:
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}
After adding the code snippets, the final fragment shader is:
#ifdef USE_LOGDEPTHBUF
uniform float logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}
See the example:
(function onLoad() {
var container, camera, scene, renderer, orbitControls;
function createModel() {
var material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}`,
fragmentShader: `
#ifdef USE_LOGDEPTHBUF
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}`,
side: THREE.DoubleSide,
});
//var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1, -2);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
orbitControls = new THREE.OrbitControls(camera);
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
createModel();
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
init();
animate();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
(function onLoad() {
var container, camera, scene, renderer, orbitControls;
function createModel() {
var material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}`,
fragmentShader: `
#ifdef USE_LOGDEPTHBUF
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}`,
side: THREE.DoubleSide,
});
//var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1, -2);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
orbitControls = new THREE.OrbitControls(camera);
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
createModel();
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
init();
animate();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
(function onLoad() {
var container, camera, scene, renderer, orbitControls;
function createModel() {
var material = new THREE.ShaderMaterial({
uniforms: {
color1: {
value: new THREE.Color('#3a0000')
},
color2: {
value: new THREE.Color('#ffa9b0')
}
},
vertexShader: `
#ifdef USE_LOGDEPTHBUF
#define EPSILON 1e-6
#ifdef USE_LOGDEPTHBUF_EXT
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
varying vec3 vNormal;
void main(void){
vNormal = normalMatrix * normalize(normal);
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
#ifdef USE_LOGDEPTHBUF
gl_Position.z = log2(max( EPSILON, gl_Position.w + 1.0 )) * logDepthBufFC;
#ifdef USE_LOGDEPTHBUF_EXT
vFragDepth = 1.0 + gl_Position.w;
#else
gl_Position.z = (gl_Position.z - 1.0) * gl_Position.w;
#endif
#endif
}`,
fragmentShader: `
#ifdef USE_LOGDEPTHBUF
#ifdef USE_LOGDEPTHBUF_EXT
#extension GL_EXT_frag_depth : enable
varying float vFragDepth;
#endif
uniform float logDepthBufFC;
#endif
uniform vec3 color1;
uniform vec3 color2;
varying vec3 vNormal;
void main(void){
vec3 view_nv = normalize(vNormal);
vec3 nv_color = view_nv * 0.5 + 0.5;
vec3 c = mix(color1, color2, nv_color.r);
gl_FragColor = vec4(c, 1.0);
#if defined(USE_LOGDEPTHBUF) && defined(USE_LOGDEPTHBUF_EXT)
gl_FragDepthEXT = log2(vFragDepth) * logDepthBufFC * 0.5;
#endif
}`,
side: THREE.DoubleSide,
});
//var material = new THREE.MeshPhongMaterial({color:'#b090b0'});
var geometry = new THREE.BoxGeometry( 1, 1, 1 );
var mesh = new THREE.Mesh(geometry, material);
scene.add(mesh);
}
function init() {
container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({
antialias: true,
logarithmicDepthBuffer: true
});
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.shadowMap.enabled = true;
container.appendChild(renderer.domElement);
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 100);
camera.position.set(0, 1, -2);
scene = new THREE.Scene();
scene.background = new THREE.Color(0xffffff);
scene.add(camera);
window.onresize = resize;
orbitControls = new THREE.OrbitControls(camera);
var helper = new THREE.GridHelper(100, 100);
helper.material.opacity = 0.25;
helper.material.transparent = true;
scene.add(helper);
var axis = new THREE.AxesHelper(1000);
scene.add(axis);
createModel();
}
function resize() {
var aspect = window.innerWidth / window.innerHeight;
renderer.setSize(window.innerWidth, window.innerHeight);
camera.aspect = aspect;
camera.updateProjectionMatrix();
}
function animate() {
requestAnimationFrame(animate);
orbitControls.update();
render();
}
function render() {
renderer.render(scene, camera);
}
init();
animate();
})();
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/97/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>
<div id="container"></div>
answered Nov 25 '18 at 12:54
Rabbid76Rabbid76
39.1k123250
39.1k123250
add a comment |
add a comment |
I assume you have tried inserting that code in your two shaders? To my understanding, that should be correct.
The error appears to be complaining about the shader not compiling, due to a reference to EPSILON
in the vertex shader body, although EPSILON
was never declared.
Try defining EPSILON
, e.g. using a macro in the shader itself:
#define EPSILON 1e-6
or pass it to the shader as a uniform. (Notice that this is just an example value; you may want to research what a suitable value for EPSILON
might be in your particular case.)
Unfortunately this will lead to a new error:THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:56: 'endifvarying' : invalid directive name ERROR: 0:57: 'gl_Position' : syntax error
– d4rty
Nov 20 '18 at 15:53
add a comment |
I assume you have tried inserting that code in your two shaders? To my understanding, that should be correct.
The error appears to be complaining about the shader not compiling, due to a reference to EPSILON
in the vertex shader body, although EPSILON
was never declared.
Try defining EPSILON
, e.g. using a macro in the shader itself:
#define EPSILON 1e-6
or pass it to the shader as a uniform. (Notice that this is just an example value; you may want to research what a suitable value for EPSILON
might be in your particular case.)
Unfortunately this will lead to a new error:THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:56: 'endifvarying' : invalid directive name ERROR: 0:57: 'gl_Position' : syntax error
– d4rty
Nov 20 '18 at 15:53
add a comment |
I assume you have tried inserting that code in your two shaders? To my understanding, that should be correct.
The error appears to be complaining about the shader not compiling, due to a reference to EPSILON
in the vertex shader body, although EPSILON
was never declared.
Try defining EPSILON
, e.g. using a macro in the shader itself:
#define EPSILON 1e-6
or pass it to the shader as a uniform. (Notice that this is just an example value; you may want to research what a suitable value for EPSILON
might be in your particular case.)
I assume you have tried inserting that code in your two shaders? To my understanding, that should be correct.
The error appears to be complaining about the shader not compiling, due to a reference to EPSILON
in the vertex shader body, although EPSILON
was never declared.
Try defining EPSILON
, e.g. using a macro in the shader itself:
#define EPSILON 1e-6
or pass it to the shader as a uniform. (Notice that this is just an example value; you may want to research what a suitable value for EPSILON
might be in your particular case.)
answered Nov 20 '18 at 14:27
BerthurBerthur
709212
709212
Unfortunately this will lead to a new error:THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:56: 'endifvarying' : invalid directive name ERROR: 0:57: 'gl_Position' : syntax error
– d4rty
Nov 20 '18 at 15:53
add a comment |
Unfortunately this will lead to a new error:THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:56: 'endifvarying' : invalid directive name ERROR: 0:57: 'gl_Position' : syntax error
– d4rty
Nov 20 '18 at 15:53
Unfortunately this will lead to a new error:
THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:56: 'endifvarying' : invalid directive name ERROR: 0:57: 'gl_Position' : syntax error
– d4rty
Nov 20 '18 at 15:53
Unfortunately this will lead to a new error:
THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog Must have a compiled vertex shader attached. ERROR: 0:56: 'endifvarying' : invalid directive name ERROR: 0:57: 'gl_Position' : syntax error
– d4rty
Nov 20 '18 at 15:53
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53391303%2fusing-webglrenderer-with-logarithmicdepthbufferset-option-set-to-true-together-w%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown