Skip to content

Conversation

@machenmusik
Copy link
Contributor

Fix #3151.

},

init: function () {
this.material = this.el.getOrCreateObject3D('mesh').material = new THREE.ShaderMaterial({
Copy link
Member

@donmccurdy donmccurdy Oct 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This predates your PR, but i think getOrCreateObject3D('mesh').material is a bad pattern. It screws with components waiting for object3dset, for example. IMO this initializer should see if a mesh is available already, and if not wait for the object3dset method.

(this has the added benefit of making it compatible with custom models, if you use a traverse(), which registerShader cannot do)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How does it mess with components waiting for object3dset?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See: #2464

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Point is, the framework should abstract all this away so you can say shader:displacement and let A-frame worry about when. That is what registerShader allows, and this entire approach completely fails to do.

Copy link
Contributor Author

@machenmusik machenmusik Oct 11, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if you use a traverse(), which registerShader cannot do

Shouldn't the material component be the one doing that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My thought was a simple recursive:true (or we can still call it traverse). I am guessing we can detect the aframe entity object3D structure and refuse to cascade, but I haven't looked.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can always make your own replacement for the material component, which obviously you do by default, but for the simple example cases that seems like overkill.

What I am not sure about is whether the model object trees have consistent DOM-ish naming, for better declarative mapping etc. I think I saw discussion on that in another issue/PR

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found that when I need a custom material, I just use a raw component. I think @donmccurdy does the same? It's simpler than hooking into material. Should we recommend that?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The idea is that if you only need to use your own (vertex and fragment) shader, that is most easily done with registerShader and then material="shader:my-shader". The examples that were given previously are actually easier to do that way (which is hopefully illustrated).

Other examples where you only need shader and not custom material, besides the ones listed, include the typical top/bottom and left/right stereo shaders we used to recommend separate geometry and/or components for.

If registerShader doesn't work for various reasons, then it does recommend creating a custom component (with this example).

I did ask for an example that actually requires custom component, but so far no one has suggested one.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nevermind, I saw this is already done as a raw component. I thought it was trying registerShader.

@machenmusik
Copy link
Contributor Author

OK so -

We seem to agree these docs are an improvement.

Both the examples (grid and displacement) are done both as registered shader and custom component, so we actually have @donmccurdy's comment whynotboth already.

Ok to merge while working #3155?

@donmccurdy
Copy link
Member

I haven't had the chance to do a thorough read-through yet, but assuming someone has reviewed for any errors then +1 from me for merging and not waiting on the other discussions.


varying vec2 vUv;
uniform vec3 color;
uniform float time;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

time1000 is a weird name. Let’s keep time. It is already consistent with other time related variables that use miliseconds in the code base

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the reason I didn't use time is because that is commonly used to represent time, but in seconds not milliseconds. Unfortunately the time type is processed as milliseconds, so I wanted to pick a different name and convert to the time in seconds that typical sharers expect. Maybe timeMsec or something more descriptive?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To clarify, there is inherent support for type time, without using a tick() handler to update anything, but it is in milliseconds rather than seconds (which is what you generally see in common sharers from Shadertoy, Shaderfrog, etc.)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the DOM and A-Frame we use miliseconds for time. I would keep the name time

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I may not be doing a good job of explaining.

The shader examples that are time-varying already use a uniform named time that is in seconds. Rather than trying to force already working shaders to rename, what I am illustrating is how to do a simple two line addition that allows the shader code to be reused without modification.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to timeMsec, and added comments in the shader to explain the conversion to seconds.


```js
AFRAME.registerComponent('custom-material', {
<script src="https://rawgit.com/aframevr/aframe/master/dist/aframe-master.min.js"></script>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason we need to be suggesting the master version in the docs?

@ngokevin do versions get automatically find/replaced when we do a release?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No reason other than not having to change it every release.

update: function () {
// Update `this.material`.
Setting raw to true uses THREE.RawShaderMaterial instead of ShaderMaterial,
so your shader strings are used as-is, for advanced shader usage.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd link to the docs for THREE.RawShaderMaterial and ShaderMaterial here.

so your shader strings are used as-is, for advanced shader usage.

maybe better to be explicit: "so built-in uniforms and attributes are not automatically added to your shader code."

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

```glsl
// vertex.glsl

#pragma glslify: pnoise3 = require(glsl-noise/periodic/3d)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I probably wouldn't go to the trouble of explaining how to set it up here, but worth noting somewhere that:

This example uses Browserify and glslify to include glsl-noise as a dependency of our shader.

(similar options are available for rollup etc.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@dmarcos
Copy link
Member

dmarcos commented Oct 12, 2017

We have an example of custom shaders already. Do we want to point to it in the docs? https://aframe.io/aframe/examples/test/shaders/

@machenmusik
Copy link
Contributor Author

@dmarcos added that example

@machenmusik
Copy link
Contributor Author

OK, I think this looks good now, unless someone has a real example to contribute of a custom shader that uses a type that registerShader doesn't support

Copy link
Member

@ngokevin ngokevin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Few changes. Thanks!

@@ -0,0 +1,26 @@
---
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this part is too thin for a separate section. I think it's OK to be contained in the material section for now. Perhaps as the API and the ecosystem around shaders possibly matures, we move it out a separate section?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The non-duplicated part here that seems worth keeping is the reference to shader repositories like ShaderToy and/or ShaderFrog (there are probably others too) and pointers toward components that help with reusing those. Where would you suggest that appear in material documentation?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps when shaders are first introduced.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like your shaderfrog gallery went away, was that intentional? Changed reference to just the shaderfrog site.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it was an empty repo 🙄

* [Live demo](https://aframe-simple-shader.glitch.me/)
* [Remix this on Glitch](https://glitch.com/edit/#!/aframe-simple-shader)
* [Live demo](https://aframe-simpler-shader.glitch.me/)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All the Glitch demos can be listed in the examples array in the header:

examples:
  - title: Grid Glitch Shader
    url: https://glitch.com/edit/#!/aframe-simpler-shader?path=client/shader-grid-glitch.js:1:0

For ease of copy/pasting, I'd remove the GLSLify build step and use multiline strings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It was that way originally (using GLSL-ify) so I left it that way; you can see that the new one I added as walkthrough does, in fact, use multi-line strings. Are you asking to make changes to the existing example instances that will retroactively alter documentation for prior versions?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can remix the Glitch and not alter the old one.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI - current examples header looks pretty unattractive, and no other good examples to follow?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a data structure, it gets rendered underneath the table of contents as a list. I think there are two Glitches you listed, can add more as we go.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just checked, there are more than two. Good list!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updated the Glitches I made, just the page and script, no more extraneous server and files

},

init: function () {
this.material = this.el.getOrCreateObject3D('mesh').material = new THREE.ShaderMaterial({
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've found that when I need a custom material, I just use a raw component. I think @donmccurdy does the same? It's simpler than hooking into material. Should we recommend that?

@ngokevin
Copy link
Member

Thanks, will work on merging this soon.

@ngokevin ngokevin merged commit 9f2f4d9 into aframevr:master Oct 18, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

4 participants