I'm trying to implement a shader with normal mapping like this example (which works fine with the older build):
http://coryg89.github.io/technical/2013/06/01/photorealistic-3d-moon-demo-in-webgl-and-javascript/
After digging into why this example won't work with the latest build, I discovered that this is using "computeTangents()" to generate the tangent variable that seems to be provided "for free" to the shader as a vertex attribute. However, I can't see anything in the docs or examples that explains how to generate these precomputed tangents with the new build. When I try to use the dFdx
functions, I get the error about standard derivatives and if I try and include those in my shader, like so:
#extension GL_OES_standard_derivatives : enable
I get the error about non pre-processor tokens.
I see that the computeTangents function has been moved to a utils file, but using against a simple cube geo I made in Maya results in a missing index value for geometry.index
. How can I generate this tangent for the vertex?
Macbook Pro
THREE.BufferGeometryUtils.computeTangents( geometry )
requires indexed-bufferGeometry.
I've been trying to figure that out. How is the index created? In the utils file, it's failing this check:
if ( index === null ||
attributes.position === undefined ||
attributes.normal === undefined ||
attributes.uv === undefined ) {
console.warn( 'THREE.BufferGeometry: Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()' );
return;
}
But I have not been able to find a working example anywhere.
As an example, I swapped out the version of Three in the moon demo above to the latest. This was using a basic SphereGeometry object. But that object has no "attributes", so cannot computeTangents like it could before. And since computing the tangent in the frag shader is giving the GL_OES_standard_derivatives error, it seems like there's no good way to apply a normal map via shader to an object. Am I missing something or have we lost some key functionality?
The support of OES_standard_derivatives
is close to 100%. So it can't be a compatibility issue.
https://webglstats.com/webgl/extension/OES_standard_derivatives
I assume you might have a problem in your shader code. Is this issue helpful for you? #6493
I tried everything discussed in that issue. If I attempt to enable that derivative, then I get the preprocessor token problem.
If you implement normal mapping by yourself, you should try stackoverflow in order to solve the problems in you shader program. Sry, but this is clearly an user issue from my point of view. As stated in the guidelines, the issue section at github is not a help site.
javascript
var foo = new THREE.SphereBufferGeometry();
THREE.BufferGeometryUtils.computeTangents( foo );
````
foo.index
Uint16BufferAttribute {uuid: "6843C992-4F6E-42FC-B6A1-184D605125D7", name: "", array: Uint16Array(240), itemSize: 1, count: 240,聽鈥
foo.attributes
normal: Float32BufferAttribute {uuid: "6F7A2481-6DF2-4B3B-A902-A2E9051BD437", name: "", array: Float32Array(189), itemSize: 3, count: 63, 鈥
position: Float32BufferAttribute {uuid: "BCB7A9E6-F467-46FC-AFDC-6EADC490CEE1", name: "", array: Float32Array(189), itemSize: 3, count: 63, 鈥
tangent: BufferAttribute {uuid: "D200D4AB-B4DF-4360-A50A-1947AF24AE1A", name: "", array: Float32Array(252), itemSize: 4, count: 63, 鈥
uv: Float32BufferAttribute {uuid: "D4FA703C-1CCB-4098-94C6-C5FC24B3CA7D", name: "", array: Float32Array(126), itemSize: 2, count: 63, 鈥
````
Could you try using that in place of the moon?
@Mugen87 I agree that Stack Overflow is a good resource, however, this is regarding a piece of functionality that used to work (proven by the working example linked to above) that has now been rendered inoperable by a recent change to the library. It seems like a valid issue to address with the contributors instead of other users.
Your example is over four years old and uses three.js
in version 63
. It's not surprising that such old code has problems with the latest version...
This is true. I should note for others, that @moraxy had the right suggestion. The demo is using Three.SphereGeometry instead of Three.SphereBufferGeometry, and changing this fixed the issue and allowed the demo to create the tangent attribute.
@Mugen87 FYI, I've set up an example (please ignore the awful formatting) in which I'm getting the derivatives error. Here is the code:
<body>
<div id='container'></div>
<script src="http://threejs.org/build/three.js"></script>
<style media="screen">
body {
overflow: hidden;
}
</style>
<script id='vertexShader' type='x-shader/x-vertex'>
varying vec2 vUv;
varying float uvScale;
void main() {
vUv = uvScale * uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
</script>
<script id='fragmentShader' type='x-shader/x-fragment'>
uniform sampler2D tex1;
mat3 cotangent_frame(vec3 N, vec3 p, vec2 uv)
{
// get edge vectors of the pixel triangle
vec3 dp1 = dFdx( p );
vec3 dp2 = dFdy( p );
vec2 duv1 = dFdx( uv );
vec2 duv2 = dFdy( uv );
// solve the linear system
vec3 dp2perp = cross( dp2, N );
vec3 dp1perp = cross( N, dp1 );
vec3 T = dp2perp * duv1.x + dp1perp * duv2.x;
vec3 B = dp2perp * duv1.y + dp1perp * duv2.y;
// construct a scale-invariant frame
float invmax = inversesqrt( max( dot(T,T), dot(B,B) ) );
return mat3( T * invmax, B * invmax, N );
}
vec3 perturb_normal( vec3 N, vec3 V, vec2 texcoord )
{
// assume N, the interpolated vertex normal and
// V, the view vector (vertex to eye)
vec3 map = texture2D(tex1, texcoord ).xyz;
map = map * 255./127. - 128./127.;
mat3 TBN = cotangent_frame(N, -V, texcoord);
return normalize(TBN * map);
}
void main(){
gl_FragColor = vec4(1.0);
}
</script>
<script>
var container;
var camera, scene, renderer;
var mesh;
var uniforms;
var controls;
init();
render();
function init() {
camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 10000);
camera.position.z = 20;
scene = new THREE.Scene();
uniforms = {
u_resolution: {type: "v2", value: new THREE.Vector2()},
uvScale: {type: "v2", value: new THREE.Vector2(1,1)},
u_time: {type: "f", value: 1.0},
u_gradient_tex: { type: "t", value: THREE.ImageUtils.loadTexture("gradient.jpg") },
u_normal_tex: { type: "t", value: THREE.ImageUtils.loadTexture("moon.jpg") },
u_projection_pos: { type: "v3", value: new THREE.Vector3(1, 0, 0) },
u_rotation: { type: "f", value: 45.0 },
u_offset: { type: "v2", value: new THREE.Vector2(0.5, 0.5) },
u_ambient_light: { type: "v3", value: new THREE.Vector3(0.5, 0.5, 0.5) },
lightPosition: { type: "v3", value: new THREE.Vector3() }
};
uniforms.u_gradient_tex.value.wrapS = uniforms.u_gradient_tex.value.wrapT = THREE.RepeatWrapping;
var material = new THREE.ShaderMaterial({
uniforms: uniforms,
vertexShader: document.getElementById('vertexShader').textContent,
fragmentShader: document.getElementById('fragmentShader').textContent
});
var radius = 100;
var xSegments = 50;
var ySegments = 50;
var geo = new THREE.SphereBufferGeometry(radius, xSegments, ySegments);
var mesh = new THREE.Mesh(geo, material);
//THREE.BufferGeometryUtils.computeTangents( geo );
mesh.position.set(0, 0, 0);
mesh.rotation.set(0, 180, 0);
scene.add(mesh);
// renderer
renderer = new THREE.WebGLRenderer({ antialias: false });
renderer.setSize(window.innerWidth, window.innerHeight);
container = document.getElementById('container');
container.appendChild(renderer.domElement);
window.addEventListener('resize', onWindowResize, false);
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
uniforms.u_resolution.value.x = renderer.domElement.width;
uniforms.u_resolution.value.y = renderer.domElement.height;
render();
}
function render() {
renderer.render(scene, camera);
}
</script>
</body>
The error I get is:
THREE.WebGLProgram: shader error: 0 gl.VALIDATE_STATUS false gl.getProgramInfoLog invalid shaders ERROR: 0:106: 'GL_OES_standard_derivatives' : extension is disabled
ERROR: 0:107: 'GL_OES_standard_derivatives' : extension is disabled
ERROR: 0:108: 'GL_OES_standard_derivatives' : extension is disabled
ERROR: 0:109: 'GL_OES_standard_derivatives' : extension is disabled
And one more example. I saw this referenced in another bug report and updated the Fiddle to use the latest build. I get the same error here, and as you can see it's just using that one line.
EDIT: If anyone comes across this issue, the solution is to addmaterial.derivatives = true;
which solves the extension disabled error.
@abogartz It is now
material.extensions.derivatives = true;
Most helpful comment
javascript var foo = new THREE.SphereBufferGeometry(); THREE.BufferGeometryUtils.computeTangents( foo );
````