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

[WIP] tiny api and example how to combine material extensions #14206

Closed
wants to merge 27 commits into from

Conversation

pailhead
Copy link
Contributor

@pailhead pailhead commented Jun 3, 2018

I made a simple example that consolidates a few features that have been discussed over the years, with a bit of help from some core changes. (around 30 lines of core added/changed to WebGLRenderer,WebGLProgram and WebGLPrograms.)

  1. a need for a Specular Glossiness StandardMaterial (GLTFLoader: Remove onBeforeRender dependency #14099, [WIP] GLTFLoader: Use node materials. #14149)
  2. a need for per channel uv transforms (GLTFLoader: Implement KHR_texture_transform extension. #13831, [WIP] GLTFLoader: Use node materials. #14149, Ambiguity with texture transformation and texture cloning #12788, GLTFLoader does not support texCoord fields #12608, GLTFLoader: Implement KHR_texture_transform extension. #13831, Support per-map per-Material UV channels, UV offset/repeat and texel scale/offset #8278, [WIP] per channel uv transform example  #14174)
  3. a simple instancing example, it shows how to do [WIP] Example for extending materials #14166 in combination with other thing when not limited by onBeforeCompile API but still using the "shader injection" approach.

http://dusanbosnjak.com/test/webGL/three-material-includes/

The example js file contains all three of these extensions, but they could be in their own files.

The code required to extend the first 2 is:

decorateMaterialWithSpecGloss(material)
decorateMaterialWithPerMapTransforms(material)

These then become immediately available:

material.glossinessMap = texture
material.specularMap = texture
gui.add( material, 'glossinessMapRotation',0,1).onChange(material.glossinessMapUpdateMatrix)
  1. actually has a conflict with the chunk names, and has a couple of lines to solve that, but it works. If the templates could be restructured a bit to give a bit more separation, these would come up in fewer places i think

  2. is just illustrative, it's a simple example and the contract between the extension and geometry is instanceOffset and instanceScale, the code just turns the geometry and adds these attributes. I'm not entirely sure why Instanced mesh #10750 was shelved, but this kind of an api would make a 3rd party package like this https://www.npmjs.com/package/three-instanced-mesh much more flexible and powerful.

  3. is an "inline" example on how to extend the stuff thats already extended and illustrates a drawback of onBeforeCompile. I wanted to remove an attribute from an extension instanceScale and use my own aIndex. If this logic is hidden in onBeforeCompile my hands are tied, but if this were in its own parseGlobalsVertex chunk then i'd have the "compiled" (parsed/unrolled) string, and i could replace this. Anyway this takes the instanced_lambert example and combines it with spec/gloss, multi uvs, and further modifies it on top of it (materials_modified).

A huge upside of this approach is that i can spend all my time in a text editor, without having to zoom and pan and click through a visual editor.

@pailhead
Copy link
Contributor Author

pailhead commented Jun 3, 2018

If someone feels really strongly that transform belongs on Texture rather than Material's channels, one can totally opt out of that extension. For example, here's the refactored GLTF (using this api) extended to be instanced roughly 1000 times. So if one only needs the spec gloss, and simple instancing this is how to do it:

http://dusanbosnjak.com/test/webGL/three-material-includes/webgl_loader_gltf_extensions.html

if(sceneInfo.name === 'BoomBox (PBR)'){
        // only one line
	decorateMaterialWithSimpleInstancing(object.children[0].material)
	
        // geometry stuff
        const size = 64
	const size_inv = 1/size
	const instances = size * size
	const scale = 1

	const instancePositionArray = new Float32Array( instances * 3 )
	const instanceScaleArray = new Float32Array( instances * 3 )
	for ( var i = 0, ii = 0 ; i < instances ; i++ ){
		instanceScaleArray[ii] = 1
		instancePositionArray[ii++] = ((i % size) * size_inv-0.5) * scale
		instanceScaleArray[ii] = 1
		instancePositionArray[ii++] = 0
		instanceScaleArray[ii] = 1
		instancePositionArray[ii++] = (Math.floor(i*size_inv) * size_inv-0.5) * scale
	}


	object.children[0].geometry = new THREE.InstancedBufferGeometry().copy(object.children[0].geometry)
	object.children[0].geometry.addAttribute( 'instanceOffset', new THREE.InstancedBufferAttribute(instancePositionArray, 3))
	object.children[0].geometry.addAttribute( 'instanceScale', new THREE.InstancedBufferAttribute(instanceScaleArray, 1))
	object.children[0].geometry.maxInstancedCount = instances
	object.children[0].frustumCulled = false

}

^btw don't know how heavy the boombox is but it seems somewhat high poly, my air is chugging, my 1080 blazed through it

@donmccurdy donmccurdy mentioned this pull request Jun 4, 2018
@pailhead
Copy link
Contributor Author

pailhead commented Jun 5, 2018

serializew

It's kinda hacking it, and i wasnt able to get rid of metalness.

@mrdoob
Copy link
Owner

mrdoob commented Jun 18, 2018

#14245 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants