-
-
Notifications
You must be signed in to change notification settings - Fork 35.6k
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
Default material shader modifier #7581
Default material shader modifier #7581
Conversation
Wow! This looks great. I wonder if anybody here knows the answer to this question: https://github.com/mrdoob/three.js/pull/7581/files#diff-e24610216374beea052f744c4643869bR86 |
Yeah, it really does look good! |
@danielribeiro umm I thought I deleted that parameter, as I just copied from another example. I guess it really depends on how the normal maps is stored, but for the one on the example is not necessary. |
A few months ago was dismissed PR from my with the same functionality (but more dirty implementation) Im afraid the same awaits this one |
@nn4e maybe the dirtiness had something to do, the prettier the solution the more chances it has to be merged 😊 |
I just deleted the builds, sorry for that :) |
This could be done in an elegant way via @sunag's node based material system? Basically this would be a customization of the normal parameter. |
API wise... How about something like this instead? var material = new THREE.MeshPhongMaterial( color: 0xAAAAAA,
specular: 0xffffff,
shininess: 10,
map: DiffuseMap,
normalMap: NormalMap
);
var enhanced = new THREE.EnhancedMaterial( material, {
uniforms: {
"time": { type: "f", value: 1.0 }
},
preVertex: [
'float angle = (150.*sin(time-position.y))*0.02;',
'transformed = vec3(transformed.x * cos(angle) - transformed.z * sin(angle), transformed.y, transformed.x * sin(angle) + transformed.z*cos(angle));',
'vNormal = vec3( vNormal.x * cos( angle ) - vNormal.z * sin( angle ), vNormal.y, vNormal.x * sin( angle ) + vNormal.z * cos( angle ) );'
].join("\n"),
preMainVertex: "uniform float time;",
}
); Actually, something like this would be better I think: var material = new THREE.MeshPhongMaterial().toShaderMaterial();
material.vertexShader.replace( '%PRE_MAIN_VERTEX%', 'uniform float time;' ); |
@mrdoob I like the second approach to convert the default material to a shader material but keeping something similar to the shadermodifier attributes. I believe it would be easier and more intuitive for the newbies than replacing strings in their own. And we could also keep track of those properties. |
This is an old PR but today I started to play again with this problem and tried @sunag's NodeMaterial. It's a very nice way to inject code using those shortcuts to the standard materials defined in three.js but I see some problems for use it in this kind of simple situations:
So I'm not sure what you think but maybe we could have this two approach together? Include something like this proposal in the base core: adding the shorcuts directly on the core and with a simple api where you could inject directly code on those shorcuts. Simple enough to prevent excesive changes on the core, so the users should know what they're doing and which attributes they're modifying. What do you think? |
That. It's possible to write something like this in-core with a minimum of code. However, in order for that to happen we'd have to clean up some more (see #8552). |
Following the discussion on #11475 |
Many times I've tried to use some of the default materials like MeshPhongMaterial but at the same time I wanted to add some kind of custom transformation, like a simple mesh deformation. To do that I needed to create a completely new shader and copy the shader from MeshPhong, add my custom deformation code and create a new ShaderMaterial.
It's really a pain so I thought It could be useful to add the possibility to include custom code inside the default materials making this changes much easier.
I've added a new material param called
shaderModifier
that is a object with the following parameters:preMainVertex
: This code will be added before themain()
in the shader code. Typically used to add uniforms declarations or custom functions.preVertex
: It's added just after thetransformed = position;
so you could add your custom code to play with thetransformed
vertex.postVertex
: It's added at the end of the vertex shader.preMainFragment
: LikepreMainVertex
it's added before themain()
in the fragment shader code.preFragment
: The same aspreVertex
but for fragment shader.postFragment
: The same aspostVertex
but for fragment shader.uniforms
: Custom uniforms added.Having this new code we could add a custom vertex shader modifier (distortion) based on a new uniform variable called
time
:Typically uses will require
preVertex
to do actual vertex transformation code ontransformed
point,preMainVertex
to define the uniform,uniforms
to access them andpostFragment
to modify thegl_FragColor
.In the previous example we defined
time
uniform. If we want to access it on the render loop we could just simple use the following line:material.shaderModifier.uniforms[ "time" ].value = time;
I've included also a simple example showing this functionality:
http://fernandojsg.com/lab/js/twist